SaTokenConfigure.java 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package com.fdkankan.sale.config;
  2. import cn.dev33.satoken.context.SaHolder;
  3. import cn.dev33.satoken.exception.NotLoginException;
  4. import cn.dev33.satoken.exception.NotPermissionException;
  5. import cn.dev33.satoken.exception.NotRoleException;
  6. import cn.dev33.satoken.filter.SaServletFilter;
  7. import cn.dev33.satoken.jwt.StpLogicJwtForMixin;
  8. import cn.dev33.satoken.jwt.StpLogicJwtForStateless;
  9. import cn.dev33.satoken.router.SaRouter;
  10. import cn.dev33.satoken.stp.SaLoginConfig;
  11. import cn.dev33.satoken.stp.StpLogic;
  12. import cn.dev33.satoken.stp.StpUtil;
  13. import com.alibaba.fastjson.JSONArray;
  14. import com.alibaba.fastjson.JSONObject;
  15. import com.alibaba.nacos.common.utils.HttpMethod;
  16. import com.fdkankan.redis.constant.RedisKey;
  17. import com.fdkankan.redis.util.RedisUtil;
  18. import com.fdkankan.sale.common.RedisKeyUtil;
  19. import com.fdkankan.sale.common.ResultCode;
  20. import com.fdkankan.sale.common.ResultData;
  21. import com.fdkankan.sale.entity.SysMenu;
  22. import com.fdkankan.sale.entity.User;
  23. import com.fdkankan.sale.exception.BusinessException;
  24. import com.fdkankan.sale.service.ISysMenuService;
  25. import com.fdkankan.sale.service.ISysUserService;
  26. import lombok.extern.slf4j.Slf4j;
  27. import org.apache.commons.lang3.StringUtils;
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.context.annotation.Bean;
  30. import org.springframework.context.annotation.Configuration;
  31. import java.util.HashMap;
  32. import java.util.List;
  33. @Configuration
  34. @Slf4j
  35. public class SaTokenConfigure {
  36. @Autowired
  37. RedisUtil redisUtil;
  38. @Autowired
  39. ISysMenuService sysMenuService;
  40. @Autowired
  41. ISysUserService sysUserService;
  42. // 注册Sa-Token的拦截器
  43. @Bean
  44. public SaServletFilter getSaServletFilter() {
  45. return new SaServletFilter()
  46. // 指定 拦截路由 与 放行路由
  47. .addInclude("/**").addExclude(
  48. "/**/sale/customer/**",
  49. "/**/sale/upload/**",
  50. "/**/test/**",
  51. "/**/sale/order/**",
  52. "/**/sale/repairInfo/**",
  53. "/**/recording/**")
  54. // 认证函数: 每次请求执行
  55. .setAuth(obj -> {
  56. // 登录认证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
  57. SaRouter.match("/**", "/service/manage/login", r ->checkLogin() );
  58. List<SysMenu> list = sysMenuService.list();
  59. for (SysMenu o : list) {
  60. String url = o.getUrl();
  61. String perm = o.getPerms();
  62. if(StringUtils.isEmpty(url) || StringUtils.isEmpty(perm)){
  63. continue;
  64. }
  65. if(StpUtil.hasRole("super-admin")){
  66. continue;
  67. }
  68. SaRouter.match(url, r -> StpUtil.checkPermission(perm));
  69. }
  70. })
  71. // 异常处理函数:每次认证函数发生异常时执行此函数
  72. .setError(e -> {
  73. SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
  74. ResultData aj ;
  75. if (e instanceof NotLoginException) { // 如果是未登录异常
  76. NotLoginException ee = (NotLoginException) e;
  77. aj = ResultData.error(ResultCode.USER_NOT_LOGIN.code(),ResultCode.USER_NOT_LOGIN.message());
  78. }
  79. else if(e instanceof NotRoleException) { // 如果是角色异常
  80. NotRoleException ee = (NotRoleException) e;
  81. aj = ResultData.error(ResultCode.NOT_ROLE.code(),ResultCode.NOT_ROLE.message());
  82. }
  83. else if(e instanceof NotPermissionException) { // 如果是权限异常
  84. NotPermissionException ee = (NotPermissionException) e;
  85. aj = ResultData.error(ResultCode.NOT_PERMISSION.code(),ResultCode.NOT_PERMISSION.message());
  86. }
  87. else if(e instanceof BusinessException) { // 如果是权限异常
  88. BusinessException ee = (BusinessException) e;
  89. aj = ResultData.error(ee.getCode(),ee.getMessage());
  90. }
  91. else { // 普通异常, 输出:500 + 异常信息
  92. aj = ResultData.error(ResultCode.SYSTEM_ERROR.code(),ResultCode.SYSTEM_ERROR.message());
  93. }
  94. return JSONObject.toJSONString(aj);
  95. })
  96. // 前置函数:在每次认证函数之前执行
  97. .setBeforeAuth(r -> {
  98. // ---------- 设置一些安全响应头 ----------
  99. SaHolder.getResponse()
  100. .setHeader("Access-Control-Allow-Origin", "*")
  101. .setHeader("Access-Control-Allow-Methods", "*")
  102. .setHeader("Access-Control-Max-Age", "3600")
  103. .setHeader("Access-Control-Allow-Headers", "*")
  104. .setServer("4dkk");
  105. // 跳过对 OPTIONS 请求的检查,否则这里会鉴权失败,导致 springboot 配置的 addCorsMappings 跨域不执行
  106. if (SaHolder.getRequest().getMethod().equals(HttpMethod.OPTIONS.toString())) {
  107. SaRouter.back();
  108. }
  109. });
  110. }
  111. private void checkLogin(){
  112. String redisKey = String.format(RedisKeyUtil.loginToken,StpUtil.getTokenValue());
  113. if(!redisUtil.hasKey(redisKey)){
  114. throw new BusinessException(ResultCode.USER_NOT_LOGIN);
  115. }
  116. //sysUserService.saveByRedisKey(redisKey);
  117. redisUtil.expire(String.format(RedisKeyUtil.loginToken,StpUtil.getTokenValue()),21600);
  118. StpUtil.checkLogin();
  119. }
  120. //Sa-Token 整合 jwt
  121. //Stateless 无状态模式 纯jwt
  122. //Mixin 混入模式 jwt 与 Redis 逻辑混合
  123. //Simple 简单模式 Token风格替换
  124. @Bean
  125. public StpLogic getStpLogicJwt() {
  126. return new StpLogicJwtForMixin();
  127. }
  128. }