1、目的
之前写项目一致都使用的是 SpringSecurity ,但总是感觉SpringSecurity用起来比较繁琐,所以就打算使用sa-token 进行权限校验以及 登录验证,角色校验,集成比较简单.
2、设计思路
整个项目 使用SpringCloud GateWay 进行网关,统一将服务注册到nacos 上去
即 mall_auth : 提供用户登录的功能
mall-mbg: 提供对数据库的查询操作
mall_common: 公共的方法
mall_product: 提供产品查询方法
gateway_test : 充当网关功能,对请求做权限校验然后对请求进行分发
3、实现过程
1、 父项目 pom 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test_sa_token</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<mybatis.version>3.5.9</mybatis.version>
<mysql-connector.version>8.0.29</mysql-connector.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
<mybatis-generator.version>1.4.1</mybatis-generator.version>
<pagehelper-starter.version>1.4.2</pagehelper-starter.version>
</properties>
<!-- 对应的子模块 -->
<modules>
<module>gateway_test</module>
<module>mall_auth</module>
<module>mall_common</module>
<module>mall_product</module>
</modules>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--feign 连接池 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- feign 中间件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- redis 服务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--Spring Cloud 相关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Spring Cloud Alibaba 相关依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- MyBatis 生成器 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis-generator.version}</version>
</dependency>
<!--MyBatis分页插件starter-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-starter.version}</version>
</dependency>
<!--Mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2、 gateway_test 项目
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>test_sa_token</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>gateway_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway_test</name>
<description>用于测试sa_token</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>mall_common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- 对应的webFlux sa_token -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml 配置
server:
port: 8201
spring:
# redis 相关配置
redis:
# Redis数据库索引(默认为0)
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
# password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
mvc:
pathmatch:
matching-strategy: ant_path_matcher
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true # 使用小写的service-id
routes: # 配置路由路径
- id: mall-auth # 认证中心
uri: lb://mall-auth
predicates:
- Path=mall-auth/**
filters:
- StripPrefix=1
- id: mall-product # 产品模块
uri: lb://mall-product
predicates:
- Path=/mall-product/**
filters:
- StripPrefix=1
sa-token:
# token 的名称 同时也是cookie 名称
token-name: satoken
# token 的有效期 单位s 默认为30天, -1代表永不过期
timeout: 2592000
# token 临时有效期(指定时间内无操作或者视为token过期) 单位 秒
activity-timeout: -1
# 是否允许同一账号并发登录(为true 时允许一起登录, 为false 时新登录时挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时, 是否共用同一个token(为true 的时候所有登录通用同一个token,为false 时每次登录新建一个 token)
is-share: false
# token 风格
token-style: uuid
bootstrap.yml 文件
spring:
profiles:
active: dev
application:
name: mall-gateway
增加SaTokenConfigure 类用于sa-token 的配置
package com.example.gateway_test.config;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* [Sa-Token 权限认证] 全局配置类
*/
@Configuration
public class SaTokenConfigure {
// 注册 Sa-Token全局过滤器
@Bean
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**") /* 拦截全部path */
// 开放地址
.addExclude("/favicon.ico")
// 鉴权方法:每次访问进入
.setAuth(obj -> {
// 登录校验 -- 拦截所有路由,并排除/account/user/doLogin用于开放登录
SaRouter.match("/**", "/mall-auth/auth/token", r -> StpUtil.checkLogin());
// // 权限认证 -- 不同模块, 校验不同权限
/* SaRouter.match("/mall-product/**", r -> StpUtil.checkRole("normal_role"));
SaRouter.match("/admin/**", r -> StpUtil.checkRole("system_role"));
SaRouter.match("/account/**", r -> StpUtil.checkRole("user"));
SaRouter.match("/admin/**", r -> StpUtil.checkRole("admin"));
SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));*/
// 更多匹配 ... */
})
.setBeforeAuth(obj -> {
// ------设置跨域响应头
SaHolder.getResponse()
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
// 有效时间
.setHeader("Access-Control-Max-Age", "3600")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*");
})
// 异常处理方法:每次setAuth函数出现异常时进入
.setError(e -> {
return SaResult.error(e.getMessage());
})
;
}
}
增加 StpInterfaceImpl 实现了sa-token 对角色与权限的查询
package com.example.gateway_test.config;
import cn.dev33.satoken.stp.StpInterface;
import com.example.common.api.RedisKey;
import com.example.common.util.RedisUtil;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/17 14:09
* @Description 对权限进行校验
*/
@Component
public class StpInterfaceImpl implements StpInterface {
@Resource
private RedisUtil redisUtil;
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 根据用户的id 来查询出对应的
Integer userId = Integer.valueOf(String.valueOf(loginId));
List<String> permissionList = redisUtil.getCacheList(RedisKey.getUserPermissionList(userId));
return permissionList;
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
// 获取缓存
Integer userId = Integer.valueOf(String.valueOf(loginId));
List<String> roleList = redisUtil.getCacheList(RedisKey.getUserRoleList(userId));
return roleList;
}
}
增加GlobalException 用于捕获全局异常类
package com.example.gateway_test.exception;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.example.common.api.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/17 13:40
* @Description 拦截全局异常类
*/
@Slf4j
public class GlobalException {
@ResponseBody
@ExceptionHandler
public CommonResult<Object> handlerException(Exception ex) {
// 异常信息
log.error("gateway服务异常信息---{}",ex.getMessage(),ex);
CommonResult<Object> objectCommonResult = null;
if(ex instanceof NotLoginException) {
objectCommonResult = CommonResult.unauthorized("未登录");
} else if(ex instanceof NotRoleException) {
objectCommonResult = CommonResult.forbidden("没有角色");
} else if(ex instanceof NotPermissionException) {
objectCommonResult = CommonResult.forbidden("没有权限");
} else {
objectCommonResult = CommonResult.failed(ex.getMessage());
}
return objectCommonResult;
}
}
其项目主类
package com.example.gateway_test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Import;
@EnableDiscoveryClient
@SpringBootApplication
@Import(value = { com.example.common.util.RedisUtil.class
})
public class GatewayTestApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayTestApplication.class, args);
}
}
3、 mall_auth 项目
这个模块处理用户登录请求
增加LoginController 类用于处理登录请求
package com.example.mall_auth.controller;
import com.example.common.api.CommonResult;
import com.example.demo.pojo.dto.LoginUserDto;
import com.example.demo.pojo.model.User;
import com.example.mall_auth.service.LoginService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/16 19:55
* @Description
*/
@RequestMapping("/auth")
@RestController
public class LoginController {
@Resource
private LoginService loginService;
@PostMapping("/token")
public CommonResult<LoginUserDto> login(@RequestBody User user) {
return CommonResult.success(loginService.login(user.getUsername(), user.getPassword()));
}
}
LoginService 接口
package com.example.mall_auth.service;
import com.example.demo.pojo.dto.LoginUserDto;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/16 20:03
* @Description
*/
public interface LoginService {
/**
* 使用sa-token 进行登录
* @param username
* @param password
* @return
*/
LoginUserDto login(String username, String password);
}
LoginServiceImpl 接口实现类
package com.example.mall_auth.service.impl;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.example.demo.mapper.UserMapper;
import com.example.demo.pojo.dto.LoginUserDto;
import com.example.demo.pojo.model.User;
import com.example.mall_auth.service.LoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/16 20:03
* @Description 登录接口
*/
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
@Resource
private UserMapper userMapper;
@Override
public LoginUserDto login(String username, String password) {
User user = userMapper.selectUmsByUserName(username);
if(user!=null && user.getPassword().compareTo(password) ==0) {
// 登录
// 用用户id 做标识,然后将生成的token 写入到缓存中
StpUtil.login(user.getId());
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
LoginUserDto loginUserDto = new LoginUserDto();
loginUserDto.setUser(user);
loginUserDto.setToken(tokenInfo);
return loginUserDto;
}
log.error("该用户---{}---登录失败",username);
return null;
}
}
对应的pom 依赖
server:
port: 8202
spring:
datasource:
url: jdbc:mysql://localhost:3306/sa?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: 123456
cloud:
nacos:
config:
file-extension: yaml
server-addr: http://localhost:8848
discovery:
server-addr: http://localhost:8848
redis:
# Redis数据库索引(默认为0)
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
# password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
sa-token:
# token 的名称 同时也是cookie 名称
token-name: satoken
# token 的有效期 单位s 默认为30天, -1代表永不过期
timeout: 100
# token 临时有效期(指定时间内无操作或者视为token过期) 单位 秒
activity-timeout: -1
# 是否允许同一账号并发登录(为true 时允许一起登录, 为false 时新登录时挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时, 是否共用同一个token(为true 的时候所有登录通用同一个token,为false 时每次登录新建一个 token)
is-share: false
# token 风格
token-style: uuid
mybatis:
mapper-locations:
- classpath:dao/*.xml
- classpath*:mapper/*.xml
# feign请求
feign:
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
pom.xml 文件内容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>test_sa_token</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>mall_auth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mall_auth</name>
<description>mall_auth实现用户登录接口</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>mall-mbg</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>mall_common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4、实现效果
使用postman 发送 查询product 的信息
得到的结果为token 无效,说明经过网关的时候被sa-token 给拦截住了。
此时我们应该访问 mall_auth 的登录服务
此时我们会发现本地的redis服务中
多出了对应的token 缓存信息。
那么此时将token信息写入到header 中,我们再次访问product 服务的时候
就可以访问到对应的结果了。
5、 功能扩展
上面实现了对登录的拦截。我们还可以利用sa-token 在网关上做权限与角色的校验。使用RABC 对登录的用户做权限与角色的判断。
我们可以在 mall_auth 启动的时候将用户信息注入到redis 中,然后在 gateway_test 服务中的StpInterfaceImpl 中实现通过userId 到缓存中查询对应的权限以及角色集合的代码。
mall_auth 中的 PermissionInit 代码
package com.example.mall_auth.init;
import com.alibaba.nacos.common.utils.MapUtils;
import com.example.common.api.RedisKey;
import com.example.common.util.RedisUtil;
import com.example.mall_auth.service.impl.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/17 14:41
* @Description
*/
@Slf4j
@Component
public class PermissionInit implements ApplicationRunner {
@Resource
private UserService userService;
@Resource
private RedisUtil redisUtil;
@Override
public void run(ApplicationArguments args) {
log.warn("初始化数据补齐--");
// 注入对应的角色信息
Map<Integer, List<String>> userRoleMap = userService.findAllUserRoleList();
if (MapUtils.isNotEmpty(userRoleMap)) {
// 查询
for (Map.Entry<Integer, List<String>> entry : userRoleMap.entrySet()) {
Integer userId = entry.getKey();
List<String> roleList = entry.getValue();
if (!CollectionUtils.isEmpty(roleList)) {
redisUtil.setCacheList(RedisKey.getUserRoleList(userId), roleList);
}
}
}
// 注入对应的权限信息
Map<Integer,List<String>> userPermissionMap = userService.findAllUserPermission();
if(MapUtils.isNotEmpty(userPermissionMap)) {
// 查询出所有的权限
for(Map.Entry<Integer,List<String>> entry : userPermissionMap.entrySet()) {
Integer userId = entry.getKey();
List<String> permissionList = entry.getValue();
if(!CollectionUtils.isEmpty(permissionList)) {
redisUtil.setCacheList(RedisKey.getUserPermissionList(userId),permissionList);
}
}
}
}
}
然后gateway_test 中的 StpInterfaceImpl 代码
package com.example.gateway_test.config;
import cn.dev33.satoken.stp.StpInterface;
import com.example.common.api.RedisKey;
import com.example.common.util.RedisUtil;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhangyang
* @version 1.0
* @Date 2023/5/17 14:09
* @Description 对权限进行校验
*/
@Component
public class StpInterfaceImpl implements StpInterface {
@Resource
private RedisUtil redisUtil;
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 根据用户的id 来查询出对应的
Integer userId = Integer.valueOf(String.valueOf(loginId));
List<String> permissionList = redisUtil.getCacheList(RedisKey.getUserPermissionList(userId));
return permissionList;
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
// 获取缓存
Integer userId = Integer.valueOf(String.valueOf(loginId));
List<String> roleList = redisUtil.getCacheList(RedisKey.getUserRoleList(userId));
return roleList;
}
}
那么我们就可以修改SaTokenConfigure 中的 权限认证部分的代码
SaRouter.match("/mall-product/**", r -> StpUtil.checkRole("normal_role"));
表示 当前登录的用户如果需要访问 mall-product 的服务则需要拥有normal_role 角色
SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
表示 当前登录的用户如果需要访问 goods 服务则需要拥有goods 的权限