package com.isu.gaswellwatch.config; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.filter.SaServletFilter; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; import cn.hutool.core.collection.CollectionUtil; import com.isu.gaswellwatch.constants.UserConstant; import com.isu.gaswellwatch.exception.BusinessException; import com.isu.gaswellwatch.service.UserService; import com.isu.gaswellwatch.vo.MenuVO; import com.isu.gaswellwatch.vo.UserLoginInfoVO; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.List; import java.util.Map; @Configuration public class SaTokenConfigure { @Resource private InterfacePermissionSettings settings; @Resource private UserService userService; // 注册 Sa-Token全局过滤器 @Bean public SaServletFilter getSaServletFilter() { return new SaServletFilter() // 拦截地址 拦截全部path .addInclude("/**") // 开放地址 .addExclude("/favicon.ico") // 鉴权方法:每次访问进入 .setAuth(obj -> { // 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录 SaRouter.match("/**") .notMatch( "/user/doLogin","/user/file/files") .check(r -> { StpUtil.checkLogin(); checkPermission(); }); }) // 异常处理方法:每次setAuth函数出现异常时进入 .setError(e -> { if(e instanceof NotLoginException){ return SaResult.error(UserConstant.NOT_LOGIN_MSG).setCode(UserConstant.NOT_LOGIN_CODE); } return SaResult.error(e.getMessage()); }) // 前置函数:在每次认证函数之前执行(BeforeAuth 不受 includeList 与 excludeList 的限制,所有请求都会进入) .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", "*"); }); } private void checkPermission() { //先判断接口是否为限制接口 HashMap> identifier = settings.getIdentifier(); String res= ""; String requestPath = SaHolder.getRequest().getRequestPath(); if(identifier == null) return; for (Map.Entry> entry : identifier.entrySet()) { if(entry.getValue().contains(requestPath)){ res = entry.getKey(); } } //是限制接口才校验,不是直接放行 if(StringUtils.isNotBlank(res)){ //获取token对应的菜单列表 UserLoginInfoVO userLoginInfoVO = (UserLoginInfoVO) StpUtil.getTokenSession().get(UserConstant.TOKEN_SESSION); List menuList = userService.getMenuList(userLoginInfoVO.getUserVO().getUsername()); if(CollectionUtil.isEmpty(menuList)) throw new BusinessException("未获取到用户菜单"); //判断菜单和标识是否合法 String menuId = SaHolder.getRequest().getHeader(UserConstant.HEADER_MENU_ID); if(StringUtils.isBlank(menuId)) throw new BusinessException("未获取到请求发出所在菜单"); boolean flag = false; for (MenuVO menuVO : menuList) { if(menuId.equals(menuVO.getId().toString())) { if(res.equals(menuVO.getIdentifier())){ flag = true; break; } } } if(!flag) throw new BusinessException("该用户没有接口" + requestPath +"的权限"); } } }