【Sa-Token|2】Sa-Token在微服务中的使用

在微服务架构中,使用 Sa-Token 进行分布式认证和权限管理需要考虑到各个服务之间的通信和 Token

的共享。以下是一个详细的教程,介绍如何在微服务中使用 Sa-Token。

1. 微服务架构介绍

假设有以下几个微服务:

  • AuthService: 负责用户认证和 Token 生成。
  • UserService: 负责用户信息管理。
  • OrderService: 负责订单管理。

2. 引入依赖

在每个微服务中引入 Sa-Token 的依赖。以 Maven 项目为例,可以在每个服务的 pom.xml 文件中添加以下依赖:

xml 复制代码
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.31.0</version>
</dependency>

3. 配置 Sa-Token

在每个微服务中配置 Sa-Token。在 application.yml 或 application.properties 文件中添加配置。例如:

yaml 复制代码
sa-token:
  token-name: satoken
  timeout: 86400
  activity-timeout: -1
  is-read-cookie: true
  is-log: false
  is-splicing: false

4. AuthService 实现

AuthService 负责用户的认证和 Token 生成。

AuthController
java 复制代码
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password) {
        // 假设这是从数据库中查找的用户信息
        if ("admin".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001);
            return "登录成功,Token: " + StpUtil.getTokenValue();
        }
        return "登录失败";
    }

    @PostMapping("/logout")
    public String logout() {
        StpUtil.logout();
        return "注销成功";
    }
}

5. 其他微服务的配置

其他微服务(如 UserService 和 OrderService)需要在请求中携带 Token 并进行验证。

配置全局拦截器

在每个微服务中配置全局拦截器以验证 Token。

java 复制代码
import cn.dev33.satoken.interceptor.SaInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SaTokenConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/auth/login", "/auth/logout");
    }
}
UserController 示例
java 复制代码
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/info")
    public String getUserInfo() {
        StpUtil.checkLogin(); // 检查是否登录
        int userId = StpUtil.getLoginIdAsInt();
        // 根据 userId 获取用户信息(省略具体逻辑)
        return "用户信息";
    }
}
OrderController 示例
java 复制代码
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
public class OrderController {

    @GetMapping("/list")
    public String getOrderList() {
        StpUtil.checkLogin(); // 检查是否登录
        int userId = StpUtil.getLoginIdAsInt();
        // 根据 userId 获取订单列表(省略具体逻辑)
        return "订单列表";
    }
}

6. 微服务之间的调用

在微服务之间调用时,需要在请求头中携带 Token。可以使用 Feign Client 进行服务间调用。

Feign 配置

添加 Feign Client 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
创建 Feign Client

例如,在 UserService 中调用 OrderService:

java 复制代码
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(name = "order-service")
public interface OrderServiceClient {

    @GetMapping("/order/list")
    String getOrderList(@RequestHeader("satoken") String token);
}
在控制器中使用 Feign Client
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private OrderServiceClient orderServiceClient;

    @GetMapping("/orders")
    public String getUserOrders() {
        StpUtil.checkLogin(); // 检查是否登录
        String token = StpUtil.getTokenValue();
        return orderServiceClient.getOrderList(token);
    }
}

7. 集成 Redis 实现分布式会话

为了在分布式系统中共享 Token,可以使用 Redis 存储会话信息。

引入 Redis 依赖

在 pom.xml 文件中添加 Redis 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置 Redis

在 application.yml 中配置 Redis 连接信息:

yaml 复制代码
spring:
  redis:
    host: localhost
    port: 6379
启用 Redis 存储

在 Sa-Token 配置类中启用 Redis 存储:

java 复制代码
import cn.dev33.satoken.dao.SaTokenDaoRedis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;

@Configuration
public class SaTokenConfig {

    @Bean
    public SaTokenDaoRedis saTokenDaoRedis(RedisConnectionFactory connectionFactory) {
        return new SaTokenDaoRedis(connectionFactory);
    }
}

8. 完整示例

以下是一个包含登录、注销、权限验证和微服务间调用的完整示例:

AuthService
java 复制代码
@RestController
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password) {
        if ("admin".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001);
            return "登录成功,Token: " + StpUtil.getTokenValue();
        }
        return "登录失败";
    }

    @PostMapping("/logout")
    public String logout() {
        StpUtil.logout();
        return "注销成功";
    }
}
UserService
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private OrderServiceClient orderServiceClient;

    @GetMapping("/info")
    public String getUserInfo() {
        StpUtil.checkLogin();
        return "用户信息";
    }

    @GetMapping("/orders")
    public String getUserOrders() {
        StpUtil.checkLogin();
        String token = StpUtil.getTokenValue();
        return orderServiceClient.getOrderList(token);
    }
}

@FeignClient(name = "order-service")
public interface OrderServiceClient {

    @GetMapping("/order/list")
    String getOrderList(@RequestHeader("satoken") String token);
}
OrderService
java 复制代码
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
public class OrderController {

    @GetMapping("/list")
    public String getOrderList(@RequestHeader("satoken") String token) {
        StpUtil.checkLogin(); // 检查是否登录
        return "订单列表";
    }
}

通过以上步骤,你已经完成了在微服务架构中使用 Sa-Token 进行分布式认证和权限管理的基本配置。你可以根据具体需求进行扩展和调整。

相关推荐
萧瑟余晖7 小时前
Dubbo SPI扩展机制详解
架构·dubbo
Shulex7 小时前
面向跨境电商多渠道消息系统的技术架构:亚马逊站内信合规对接与自动化执行链路设计
运维·架构·自动化
吴建旭 智宅焕9 小时前
AI搜索时代的智能家居交付知识架构:官网作为可信一手信息源与全国交付基础设施
人工智能·架构·智能家居
孟健9 小时前
出海开发者资金合规:从港卡结汇到完税申报实操
后端·架构
梦帮科技9 小时前
领域认知知识库图谱注入:从双式记账图网络到高质量问答对自动化合成流水线
运维·网络·数据库·人工智能·矩阵·架构·自动化
逐流人9 小时前
Ceph分布式存储集群配置与池管理:从配置优先级到PG、复本池与纠删码池
运维·分布式·ceph·云原生·云计算·rados
海宇服务10 小时前
零信任架构实战:基于海宇车型识别精准构建自动化定损网关
运维·人工智能·架构·自动化
悟天特斯10 小时前
边缘计算赋能楼宇智能化:云边协同的实时闭环与自治架构
人工智能·架构·边缘计算
爱学习的程序媛11 小时前
2. 智能应用开发技术栈清单
ai·架构·系统架构·ai应用·智能体开发·智能应用开发
m0_5873830011 小时前
24小时自助健身房软硬件解决方案实战指南:从架构设计到部署实施
java·spring·小程序·架构·需求分析