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

相关推荐
VinciYan7 分钟前
Apache APISIX遇到504超时的解决办法
网络·网关·微服务·apache·apisix·开源网关
陈y_d18 分钟前
一文介绍 Tapable 的特性和使用,助力理解 webpack 插件架构!
前端·javascript·webpack·架构
马各马它1 小时前
kubernetes给指定用户分配调用k8s的api权限
云原生·容器·kubernetes
小明java问道之路1 小时前
已解决javax.xml.datatype.DatatypeConfigurationException异常的正确解决方法,亲测有效!!!
java·linux·服务器·后端·架构·exception·error
MinIO官方账号3 小时前
AI/ML 数据湖参考架构架构师指南
服务器·人工智能·云原生·容器·架构·kubernetes
科技之歌3 小时前
数字时代的软件架构:持续架构的兴起与架构师角色的转变
java·微服务·架构
InterestingFigure5 小时前
docker安装使用
运维·docker·云原生·容器·eureka
MinIO官方账号9 小时前
在 Equinix 上使用 MinIO 控制云数据成本
人工智能·云原生·容器·架构
liuxin334455669 小时前
Eureka区域感知路由:优化微服务架构的地理感知负载均衡
微服务·eureka·架构
研究司马懿12 小时前
【云原生】Kubernetes网络管理实操
云原生·容器·kubernetes·k8s