【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.ymlapplication.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 进行分布式认证和权限管理的基本配置。你可以根据具体需求进行扩展和调整。

相关推荐
江米小枣tonylua35 分钟前
译:设计生产级 RAG 架构
架构
怕浪猫6 小时前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构
怕浪猫7 小时前
哪些软件对 Chrome DevTools Protocol 频繁使用
人工智能·架构·前端框架
Jack2013 小时前
HarmonyOS APP事件驱动大揭秘
架构
米丘14 小时前
微前端之 Web Components 完全指南
微服务·html
秋播14 小时前
国内本地WSL2编译rancher源码
云原生
Colin草率地做慢慢地改14 小时前
关于QuickStore这个项目的重构(2)- 数据库建表文件
后端·面试·架构
candyTong1 天前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
唐某人丶1 天前
从画架构图开始:架构分析与进阶指南
架构