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

相关推荐
昌sit!5 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
Dann Hiroaki8 小时前
GPU架构概述
架构
茶馆大橘8 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
北漂IT民工_程序员_ZG9 小时前
k8s集群安装(minikube)
云原生·容器·kubernetes
coding侠客9 小时前
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
微服务·云原生·架构
lipviolet10 小时前
架构系列---高并发
架构
Phodal10 小时前
架构赋能 AI:知识工程推动下的软件架构数字化
人工智能·架构
lexusv8ls600h10 小时前
微服务设计模式 - 网关路由模式(Gateway Routing Pattern)
spring boot·微服务·设计模式
曹申阳12 小时前
2. JVM的架构模型和生命周期
jvm·架构
车载诊断技术13 小时前
电子电气架构 --- 整车控制系统
网络·架构·汽车·soa·电子电器架构