1. 为什么要在Spring Cloud Gateway中集成Sa-Token在微服务架构中API网关作为所有请求的入口承担着重要的安全防护职责。传统做法是在每个微服务中单独实现认证鉴权逻辑但这会导致大量重复代码和安全策略不一致的问题。而将认证鉴权下沉到网关层可以实现统一的安全管控。Sa-Token作为一个轻量级Java权限认证框架相比Spring Security等传统方案有几个显著优势配置简单学习曲线平缓支持多种认证方式JWT、OAuth2、SSO等提供了丰富的权限控制注解内置了会话管理、踢人下线等实用功能当Sa-Token遇上Spring Cloud Gateway可以发挥112的效果。网关负责统一的认证拦截微服务只需关注业务逻辑安全策略通过网关集中管理。这种架构既保证了安全性又避免了代码重复。2. 环境准备与基础配置2.1 创建Spring Cloud Gateway项目首先使用Spring Initializr创建一个基础项目选择以下依赖GatewayLombokSa-Token需手动添加依赖在pom.xml中添加Sa-Token依赖dependency groupIdcn.dev33/groupId artifactIdsa-token-reactor-spring-boot-starter/artifactId version1.34.0/version /dependency dependency groupIdcn.dev33/groupId artifactIdsa-token-dao-redis-jackson/artifactId version1.34.0/version /dependency2.2 配置Sa-Token基础参数在application.yml中添加基础配置sa-token: # token名称 token-name: satoken # token有效期单位秒 timeout: 86400 # token临时有效期单位秒 activity-timeout: 1800 # 是否允许同一账号并发登录 is-concurrent: true # 在多人登录同一账号时是否共用一个token is-share: false # token风格 token-style: uuid # 是否输出操作日志 is-log: true提示activity-timeout表示token无操作后的失效时间这个配置可以有效防止token被长期滥用。3. 实现认证拦截逻辑3.1 创建全局过滤器在Spring Cloud Gateway中我们需要通过自定义全局过滤器来实现认证拦截Component public class SaTokenFilter implements GlobalFilter, Ordered { Override public MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request exchange.getRequest(); ServerHttpResponse response exchange.getResponse(); // 获取请求路径 String path request.getURI().getPath(); // 放行登录接口 if(/auth/login.equals(path)) { return chain.filter(exchange); } // 检查token是否有效 try { StpUtil.checkLogin(); } catch (NotLoginException e) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } // 检查权限 if(!StpUtil.hasPermission(getPermissionString(path))) { response.setStatusCode(HttpStatus.FORBIDDEN); return response.setComplete(); } return chain.filter(exchange); } Override public int getOrder() { return -100; } private String getPermissionString(String path) { // 实现路径到权限字符串的转换逻辑 return path.replaceAll(/, :); } }3.2 实现登录接口创建一个AuthController处理登录请求RestController RequestMapping(/auth) public class AuthController { PostMapping(/login) public Result login(RequestBody LoginDto dto) { // 模拟用户验证 if(admin.equals(dto.getUsername()) 123456.equals(dto.getPassword())) { // 登录并返回token StpUtil.login(10001); return Result.success(StpUtil.getTokenValue()); } return Result.fail(用户名或密码错误); } GetMapping(/logout) public Result logout() { StpUtil.logout(); return Result.success(); } }4. 高级功能实现4.1 集成Redis实现分布式会话在生产环境中我们需要将会话信息存储在Redis中以实现分布式环境下的会话共享添加Redis依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency配置Redis连接spring: redis: host: localhost port: 6379 password: database: 0配置Sa-Token使用Redissa-token: # 配置token持久化到Redis token-prefix: satoken: is-share: true is-read-body: false is-read-head: true is-v: false # 配置Redis连接 >Component public class DynamicPermissionLoader implements StpInterface { Override public ListString getPermissionList(Object loginId, String loginType) { // 这里可以从数据库或其他存储中动态加载权限 ListString permissionList new ArrayList(); // 模拟从数据库加载权限 if(loginId.equals(10001L)) { permissionList.add(user:add); permissionList.add(user:delete); } return permissionList; } Override public ListString getRoleList(Object loginId, String loginType) { // 角色逻辑类似 return Collections.emptyList(); } }5. 常见问题与解决方案5.1 跨域问题处理当网关需要处理跨域请求时可以在配置中添加CORS配置Configuration public class CorsConfig { Bean public CorsWebFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedMethod(*); config.addAllowedOrigin(*); config.addAllowedHeader(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(new PathPatternParser()); source.registerCorsConfiguration(/**, config); return new CorsWebFilter(source); } }5.2 性能优化建议缓存权限数据权限数据通常变化不频繁可以适当缓存减少数据库查询合理设置token有效期根据业务需求平衡安全性和用户体验使用JWT模式对于无状态服务可以考虑使用Sa-Token的JWT模式监控token使用情况定期检查token的创建和销毁情况发现异常及时处理5.3 安全加固措施HTTPS强制生产环境必须使用HTTPS敏感操作二次验证对于关键操作可以要求重新输入密码IP绑定重要接口可以绑定IP防止token被盗用定期更换密钥如果使用JWT模式应定期更换签名密钥6. 测试与验证6.1 测试登录流程使用Postman或curl测试登录接口curl -X POST http://localhost:8080/auth/login \ -H Content-Type: application/json \ -d {username:admin,password:123456}预期返回{ code: 200, msg: 登录成功, data: d8f7e342-5a7d-4b1a-9c3f-2e5d6c7b8a9a }6.2 测试受保护接口使用获取到的token测试受保护接口curl -X GET http://localhost:8080/api/protected \ -H satoken: d8f7e342-5a7d-4b1a-9c3f-2e5d6c7b8a9a6.3 测试权限控制测试没有权限的接口curl -X GET http://localhost:8080/api/admin \ -H satoken: d8f7e342-5a7d-4b1a-9c3f-2e5d6c7b8a9a预期返回403状态码。7. 生产环境部署建议配置集群模式如果网关需要部署多个实例确保Redis配置正确启用HTTPS使用Nginx或负载均衡器配置HTTPS终止监控告警设置Sa-Token相关指标的监控日志审计记录关键操作的日志便于事后审计定期演练模拟token失效、权限变更等场景验证系统行为在实际项目中我们发现Sa-Token与Spring Cloud Gateway的集成确实能大幅简化微服务的安全管理。特别是在权限动态加载和会话共享方面Sa-Token提供了非常便捷的API。不过也需要注意这种架构将安全责任集中到了网关层因此网关的高可用性变得尤为重要。