淘宝做详情页的网站百度账户
对接SaToken @SaCheckEL 鉴权注解
文章目录
- 对接SaToken @SaCheckEL 鉴权注解
- 前言
- 一、引入插件和配置SaToken属性配置
- 二、配置
- 1.自定义SaTokenInterceptor并注入Bean
- 2.WebMvcConfig配置SaTokenInterceptor,拦截所有请求路径
- 三、重载SaToken权限接口和方法注入@SaCheckEL
- 1.重载SaToken权限接口
- 2.控制层注入@SaCheckEL
前言
原生SpringBoot 2.6.3、Spring 5.3.25(JDK8) 框架系统 对接SaToken 身份认证,使用 SpEL 表达式进行资源请求的鉴权。
一、引入插件和配置SaToken属性配置
<!-- Sa-Token 权限认证,用于启动SaTokenContext实现 --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.40.0</version></dependency><!-- Sa-Token 注解鉴权使用 EL 表达式 --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-el</artifactId><version>1.40.0</version></dependency>
sa-token:# token前缀token-prefix: Bearer# token名称 (同时也是cookie名称)token-name: Token# token有效期,单位s 默认12小时, -1代表永不过期timeout: 43200# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒active-timeout: -1# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)is-concurrent: true# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)is-share: false# token风格token-style: uuid# 是否输出操作日志is-log: false
二、配置
1.自定义SaTokenInterceptor并注入Bean
SaTokenInterceptor类
@Component
@Slf4j
public class SaTokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {log.debug("------------>进入拦截器SaTokenInterceptor:{}", handler.toString());response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");response.setHeader("Access-Control-Max-Age", "86400");response.setHeader("Access-Control-Allow-Headers", "*");response.setCharacterEncoding("UTF-8");response.setContentType("application/json;charset=UTF-8");//当请求路径包含/doc.html(swagger文档),跳过Token验证if ( swaggerDocSkipToken(request.getRequestURI())) {return true;}String token = request.getHeader("satoken");String baseToken = request.getHeader("token");SaSession tokenSession = null;if (StrUtil.isEmpty(baseToken) || StrUtil.isEmpty(token)) {PrintWriter out = response.getWriter();QuantdoResponse resp = new QuantdoResponse();log.info("SaTokenInterceptor:Satoken=" + token + ",Token=" + baseToken + "为空!");resp.setCode(OrderNotLoginException.TOKEN_TIMEOUT_CODE);resp.setMessage(OrderNotLoginException.TOKEN_TIMEOUT_MESSAGE);out.append(JSONObject.toJSONString(resp));return false;}if (StrUtil.isNotBlank(token)) {tokenSession = StpUtil.getTokenSessionByToken(token);}if (tokenSession != null ) {Long userId = (Long) tokenSession.getLoginId(); return true;} else {PrintWriter out = response.getWriter();QuantdoResponse resp = new QuantdoResponse();log.info("SaTokenInterceptor:未获取到登录用户信息!"); resp.setCode(OrderNotLoginException.NOT_VALID_EMP_CODE);return false;}}else{PrintWriter out = response.getWriter();QuantdoResponse resp = new QuantdoResponse();log.info("SaTokenInterceptor:未获取到令牌satoken!");resp.setCode(OrderNotLoginException.TOKEN_TIMEOUT_CODE);out.append(JSONObject.toJSONString(resp));return false;}}//Swagger Docpublic static final boolean swaggerDocSkipToken(String requestURL){if (requestURL.contains("/doc.html") || requestURL.contains(".js") || requestURL.contains(".css")|| requestURL.contains(".ico") || requestURL.contains("/swagger-resources")|| requestURL.contains("/api-docs") ) {return true;}else{return false;}}
}
SaTokenConfig 类注入SaTokenInterceptor Bean
package com.isoftstone.order.service.config;
import com.isoftstone.order.service.interceptor.SaTokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class SaTokenConfig {@Beanpublic SaTokenInterceptor getSaTokenInterceptor() {return new SaTokenInterceptor();}
}
2.WebMvcConfig配置SaTokenInterceptor,拦截所有请求路径
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate SaTokenInterceptor saTokenInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(saTokenInterceptor).addPathPatterns("/**") // 拦截所有请求路径.excludePathPatterns("/login", "/assets/**"); // 排除登录和注册接口}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();ObjectMapper objectMapper = new ObjectMapper();SimpleModule module = new SimpleModule();module.addSerializer(Long.class, ToStringSerializer.instance);module.addSerializer(Long.TYPE, ToStringSerializer.instance);objectMapper.registerModule(module);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);converter.setObjectMapper(objectMapper);converters.add(0,converter);}
}
三、重载SaToken权限接口和方法注入@SaCheckEL
1.重载SaToken权限接口
/*** @Description 工单权限校验,完成 Sa-Token 的自定义权限验证扩展* @Date 2025/2/18 16:11* @Created by chenjun*/
@Component
@Slf4j
public class OrderStpInterfaceImpl implements StpInterface {@Autowiredprivate UserAndRoleService userAndRoleService;@Resourceprivate StringRedisUtil stringRedisUtil;public static final String env = "test";//'local'环境跳过Permission认证/*** 通过用户id查询用户基础资源表code集合,单个资源表code如:tenant:tenant:user:add* @param loginId 账号id:登录defUser实体id* @param loginType 账号类型* @return "tenant:tenant:user|tenant:tenant:user:query|tenant:tenant:user:add|tenant:tenant:user:delete|tenant:tenant:user:edit";**/@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {List<String> resourceCodes = userAndRoleService.getMenuResourceCodeByUser(loginId);return resourceCodes;}@Overridepublic List<String> getRoleList(Object loginId, String loginType) {return null;}
}
2.控制层注入@SaCheckEL
用户控制层UserRest 注入@SaCheckEL
@Api(tags = {"用户控制层"})
@RestController
@RequestMapping("/userRest/")
public class UserRest {@Autowiredprivate UserService userService;//用户查询@SaCheckEL("stp.checkPermission('tenant:tenant:user:query')")@GetMapping("")public List<OrderWorkListResp> query(){.....}//用户增加@SaCheckEL("stp.checkPermission('tenant:tenant:user:add')")@PostMapping("")public boolean add(User vo){.....}//用户编辑@SaCheckEL("stp.checkPermission('tenant:tenant:user:edit')")@PutMapping("")public boolean edit(User vo){.....}
}
注明:
多个权限注入方法@SaCheckEL(“stp.checkPermissionOr(‘tenant:tenant:user:query’,‘tenant:tenant:user:add’)”)
@SaCheckEL(“stp.checkPermissionAnd(‘tenant:tenant:user:query’,‘tenant:tenant:user:add’)”)
参考 SpEL 表达式注解鉴权