微服务使用Sa-token鉴权
为了统一多个系统的认证,选择了Sa-token来做鉴权、认证、授权、单点登录。
首先区分这几个名词
- 认证:确认访客的身份。像身份证、账号密码、二维码等。
- 授权:赋予访客指定范围的资源操作权限。像钥匙、门禁卡。
- 鉴权:对声明的身份信息真实性进行确认。像门禁卡需要通过门禁卡识别器。
- 权限控制:判断操作是否允许/禁止。像管理员和普通员工权限范围不一致。
顺序:先认证、授权、鉴权、最后权限控制
简单架构图
方案实现
SpringGateway
依赖
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.34.0</version>
</dependency>
<!-- 提供Redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
注册Sa-token全局过滤器
@Configuration
public class SaTokenConfig {
/**
* 注册Sa-Token全局过滤器
*/
@Bean
public SaReactorFilter getSaReactorFilter(IgnoreUrlsConfig ignoreUrlsConfig) {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
// 开放地址
.addExclude("/favicon.ico")
.addExclude("/admin/registerAdmin")
// 鉴权方法:每次访问进入
.setAuth(obj -> { SaRouter.match("/**")
.notMatch(ignoreUrlsConfig.getUrls())
.check(r->{
StpUtil.checkLogin();
});
})
// setAuth方法异常处理
.setError(e -> {
// 设置错误返回格式为JSON
return SaResult.error(ResultCodeEnum.PERMISSION_NO_ACCESS.getMsg());
})
;
}
}
白名单路径
@Data
@Component
@ConfigurationProperties(prefix="secure.ignore")
public class IgnoreUrlsConfig {
private List<String> urls;
}
Auth 只要集成Sa-Token并实现登录接口即可,非常简单。
实现在微服务之间传递token原理就是在进行feign调用时将token塞入header头中。配置在发起调用方。
@Component
public class FeignRequestInterceptor {
@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
//1、使用RequestContextHolder拿到刚进来的请求数据
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
//老请求
HttpServletRequest request = requestAttributes.getRequest();
if (request != null) {
//2、同步请求头的数据(主要是cookie)
//把老请求的cookie值放到新请求上来,进行一个同步
//String cookie = request.getHeader("Cookie");
String authorization = request.getHeader("Authorization");
template.header("Authorization",authorization);
}
}
}
};
}
}