diff --git a/smart-admin-api/pom.xml b/smart-admin-api/pom.xml index 0faa59f4..37e2f4ae 100644 --- a/smart-admin-api/pom.xml +++ b/smart-admin-api/pom.xml @@ -125,13 +125,6 @@ ${sa-token-version} - - - cn.dev33 - sa-token-jwt - 1.35.0.RC - - diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/SaTokenConfig.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/SaTokenConfig.java index 598a6530..0df62f98 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/SaTokenConfig.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/SaTokenConfig.java @@ -3,10 +3,13 @@ package net.lab1024.sa.admin.config; import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; -import net.lab1024.sa.common.config.UrlConfig; +import net.lab1024.sa.admin.module.system.menu.service.MenuCacheService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.List; + /** * sa-token 配置 * @@ -16,6 +19,9 @@ import org.springframework.context.annotation.Configuration; @Configuration public class SaTokenConfig { + @Autowired + private MenuCacheService menuService; + /** * 定义 Sa-Token 拦截器,定义详细认证规则 */ @@ -23,12 +29,9 @@ public class SaTokenConfig { public SaInterceptor saInterceptor() { // 关闭注解鉴权 只做路由拦截校验 return new SaInterceptor(handler -> { - /** - * 每个路由 都做为一个权限点 - * TODO listen from定义的api - * from menu数据表已选择的api - */ - UrlConfig.AUTH_URL_LIST.forEach(url -> SaRouter.match(url, r -> StpUtil.checkPermission(url))); + // 查询数据表中 需要校验权限的url + List urlList = menuService.queryNeedCheckPermissionsUrl(); + urlList.forEach(url -> SaRouter.match(url, r -> StpUtil.checkPermission(url))); }).isAnnotation(false); } } diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java index 25a52cb4..6ea73889 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java @@ -1,13 +1,9 @@ package net.lab1024.sa.admin.interceptor; -import cn.dev33.satoken.stp.StpUtil; -import cn.hutool.core.convert.NumberWithFormat; import com.google.common.collect.Lists; import net.lab1024.sa.common.common.domain.RequestUser; import net.lab1024.sa.common.common.enumeration.UserTypeEnum; import net.lab1024.sa.common.common.interceptor.AbstractInterceptor; -import net.lab1024.sa.common.common.util.SmartEnumUtil; -import net.lab1024.sa.common.module.support.token.TokenService; import org.springframework.context.annotation.Configuration; import javax.servlet.http.HttpServletRequest; @@ -23,6 +19,24 @@ import java.util.List; @Configuration public class AdminInterceptor extends AbstractInterceptor { + /** + * 此处可根据需要 + * 自行查询用户信息 + */ + @Override + public RequestUser getDevUser(Long userId) { + RequestUser requestUser = new RequestUser(); + requestUser.setUserId(userId); + requestUser.setUserName("dev"); + requestUser.setUserType(this.getUserType()); + return requestUser; + } + + @Override + public UserTypeEnum getUserType() { + return UserTypeEnum.ADMIN_EMPLOYEE; + } + /** * 配置拦截路径 * @@ -33,27 +47,16 @@ public class AdminInterceptor extends AbstractInterceptor { return Lists.newArrayList("/**"); } - @Override - public void checkSaToken() { - StpUtil.checkLogin(); - } - - @Override - public RequestUser getRequestUser() { - // 获取额外数据 - Integer userType = ((NumberWithFormat) StpUtil.getExtra(TokenService.EXTRA_KEY_USER_TYPE)).intValue(); - UserTypeEnum userTypeEnum = SmartEnumUtil.getEnumByValue(userType, UserTypeEnum.class); - String userName = (String) StpUtil.getExtra(TokenService.EXTRA_KEY_USER_NAME); - String loginId = (String) StpUtil.getLoginId(); - - // 当前请求对象 - RequestUser requestUser = new RequestUser(); - requestUser.setUserId(TokenService.getUserId(loginId)); - requestUser.setUserName(userName); - requestUser.setUserType(userTypeEnum); - return requestUser; - } - + /** + * 如果没有需要处理的业务 + * 那就没有必要重写了 可以删除这个方法 + * + * @param request + * @param response + * @param handler + * @return + * @throws Exception + */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { boolean isHandle = super.preHandle(request, response, handler); diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeePermissionService.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeePermissionService.java index d8ef44f3..94b00dba 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeePermissionService.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeePermissionService.java @@ -1,17 +1,24 @@ package net.lab1024.sa.admin.module.system.employee.service; +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.session.SaSessionCustomUtil; import cn.dev33.satoken.stp.StpInterface; -import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; -import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import cn.dev33.satoken.stp.StpUtil; +import com.google.common.collect.Lists; import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.lab1024.sa.admin.module.system.role.dao.RoleMenuDao; import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; import net.lab1024.sa.admin.module.system.role.service.RoleMenuService; +import net.lab1024.sa.common.common.enumeration.UserTypeEnum; import net.lab1024.sa.common.module.support.token.TokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -33,7 +40,22 @@ public class EmployeePermissionService implements StpInterface { private RoleMenuService roleMenuService; @Autowired - private EmployeeDao employeeDao; + private RoleMenuDao roleMenuDao; + + /** + * 员工关联权限 缓存key + */ + private static final String USER_ROLE_CACHE_KEY = "RoleList"; + + /** + * 角色关联功能点 缓存key + */ + private static final String ROLE_CACHE_KEY = "role:"; + + /** + * 角色关联功能点 缓存key + */ + private static final String ROLE_PERMISSION_CACHE_KEY = "PermissionList"; /** * 查询用户拥有的前端菜单项 用于登陆返回 前端动态路由配置 @@ -48,18 +70,61 @@ public class EmployeePermissionService implements StpInterface { @Override public List getPermissionList(Object loginId, String loginType) { - Long employeeId = TokenService.getUserId((String) loginId); + // 权限集合 + List permissionList = new ArrayList<>(); - // TODO listen 待做权限缓存 - EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); - List menuList = this.getEmployeeMenuAndPointsList(employeeId, employeeEntity.getAdministratorFlag()); - return menuList.stream() - .filter(e -> MenuTypeEnum.POINTS.equalsValue(e.getMenuType())) - .map(MenuVO::getApiPerms).distinct().collect(Collectors.toList()); + // 遍历角色列表,查询拥有的权限 + List roleList = this.getRoleList(loginId, loginType); + for (String roleId : roleList) { + // 查询缓存 + SaSession roleSession = SaSessionCustomUtil.getSessionById(ROLE_CACHE_KEY + roleId); + List list = roleSession.get(ROLE_PERMISSION_CACHE_KEY, () -> { + // 从数据库查询这个角色所拥有的权限列表 + return roleMenuDao.selectMenuListByRoleIdList(Lists.newArrayList(Long.parseLong(roleId)), false) + .stream() + .filter(e -> MenuTypeEnum.POINTS.equalsValue(e.getMenuType())) + .map(MenuEntity::getApiPerms).filter(Objects::nonNull).distinct() + .collect(Collectors.toList()); + }); + permissionList.addAll(list); + } + // 返回权限集合 + return permissionList; } @Override public List getRoleList(Object loginId, String loginType) { - return null; + SaSession session = StpUtil.getSessionByLoginId(loginId); + // 查询员工关联角色缓存 + Long employeeId = TokenService.getUserId((String) loginId); + return session.get(USER_ROLE_CACHE_KEY, () -> { + // 数据库中查询员工角色 + return roleEmployeeService.getRoleIdList(employeeId).stream().map(String::valueOf).collect(Collectors.toList()); + }); + } + + /** + * 清理角色关联权限 缓存 + * TODO listen 待调用 + * + * @param roleId + */ + public static void clearRoleCache(Long roleId) { + SaSessionCustomUtil.deleteSessionById(ROLE_CACHE_KEY + roleId); + } + + /** + * 清理 员工关联角色 缓存 + * TODO listen 待调用 + * + * @param employeeId + */ + public static void clearUserRoleCache(Long employeeId) { + String loginId = TokenService.generateLoginId(employeeId, UserTypeEnum.ADMIN_EMPLOYEE); + SaSession session = StpUtil.getSessionByLoginId(loginId, false); + if (null == session) { + return; + } + session.delete(USER_ROLE_CACHE_KEY); } } diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java index 5a7fd6e1..60729bea 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java @@ -73,7 +73,7 @@ public class LoginController { return loginService.getCaptcha(); } - // TODO listen + // TODO listen 测试待删除 @NoNeedLogin @ApiOperation("测试权限 @listen") @GetMapping("/listen/test") diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java index 06c21540..a32d183f 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java @@ -1,6 +1,8 @@ package net.lab1024.sa.admin.module.system.menu.constant; +import lombok.AllArgsConstructor; +import lombok.Getter; import net.lab1024.sa.common.common.enumeration.BaseEnum; /** @@ -12,6 +14,8 @@ import net.lab1024.sa.common.common.enumeration.BaseEnum; * @Email lab1024@163.com * @Copyright 1024创新实验室 ( https://1024lab.net ) */ +@Getter +@AllArgsConstructor public enum MenuTypeEnum implements BaseEnum { /** * 目录 @@ -26,23 +30,7 @@ public enum MenuTypeEnum implements BaseEnum { */ POINTS(3, "功能点"); - private Integer value; + private final Integer value; - private String desc; - - - MenuTypeEnum(Integer value, String desc) { - this.value = value; - this.desc = desc; - } - - @Override - public Integer getValue() { - return value; - } - - @Override - public String getDesc() { - return desc; - } + private final String desc; } diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuCacheService.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuCacheService.java new file mode 100644 index 00000000..97a5e56f --- /dev/null +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuCacheService.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.admin.module.system.menu.service; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import lombok.SneakyThrows; +import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum; +import net.lab1024.sa.admin.module.system.menu.dao.MenuDao; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 功能菜单业务 + * + * @author Turbolisten + * @date 2023/7/20 19:04 + */ +@Service +public class MenuCacheService { + + @Autowired + private MenuDao menuDao; + + private static final Cache> MENU_URL_CACHE = CacheBuilder.newBuilder().build(); + + /** + * 查询数据表中 需要校验权限的url + * + * @return + */ + @SneakyThrows + public List queryNeedCheckPermissionsUrl() { + return MENU_URL_CACHE.get("MENU_URL_CACHE", () -> { + // TODO listen 待确定哪个字段做为url + return menuDao.queryMenuByType(MenuTypeEnum.POINTS.getValue(), false, false) + .stream() + .map(MenuEntity::getApiPerms) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + }); + } + + public static void clearCache() { + MENU_URL_CACHE.invalidateAll(); + } + +} diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java index 4b3fa693..0b8f1bd6 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java @@ -65,6 +65,12 @@ public class MenuService { menuEntity.setApiPerms(perms); } menuDao.insert(menuEntity); + + // 清除权限缓存 + if (MenuTypeEnum.POINTS.equalsValue(menuEntity.getMenuType())) { + MenuCacheService.clearCache(); + } + return ResponseDTO.ok(); } @@ -102,6 +108,11 @@ public class MenuService { menuEntity.setApiPerms(perms); } menuDao.updateById(menuEntity); + + // 清除权限缓存 + if (MenuTypeEnum.POINTS.equalsValue(menuEntity.getMenuType())) { + MenuCacheService.clearCache(); + } return ResponseDTO.ok(); } @@ -118,8 +129,11 @@ public class MenuService { return ResponseDTO.userErrorParam("所选菜单不能为空"); } menuDao.deleteByMenuIdList(menuIdList, employeeId, Boolean.TRUE); - //孩子节点也需要删除 + // 子节点也需要删除 this.recursiveDeleteChildren(menuIdList, employeeId); + + // 清除权限缓存 + MenuCacheService.clearCache(); return ResponseDTO.ok(); } diff --git a/smart-admin-api/sa-common/pom.xml b/smart-admin-api/sa-common/pom.xml index 57a6c9c9..84b1161e 100644 --- a/smart-admin-api/sa-common/pom.xml +++ b/smart-admin-api/sa-common/pom.xml @@ -60,11 +60,6 @@ sa-token-redis-jackson - - - cn.dev33 - sa-token-jwt - diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/constant/StringConst.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/constant/StringConst.java index 2a40152d..0dcaf849 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/constant/StringConst.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/constant/StringConst.java @@ -26,6 +26,11 @@ public class StringConst { */ public static final String HORIZONTAL = "-"; + /** + * 全局通用 冒号 + */ + public static final String COLON = ":"; + /** * 全局通用分隔符 */ diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/domain/RequestUser.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/domain/RequestUser.java index e7ef34a9..3d295eca 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/domain/RequestUser.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/domain/RequestUser.java @@ -31,13 +31,7 @@ public class RequestUser { */ private UserTypeEnum userType; - /** - * TODO listen 准备移除 - * 为了其他地方不报错 - */ - @Deprecated private String ip; - @Deprecated private String userAgent; } diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/SystemEnvEnum.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/SystemEnvEnum.java index 577f9ed9..6889107d 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/SystemEnvEnum.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/SystemEnvEnum.java @@ -19,28 +19,28 @@ public enum SystemEnvEnum implements BaseEnum { /** * dev */ - DEV(SystemEnvironmentNameConst.DEV, "开发环境"), + DEV(EnvConst.DEV, "开发环境"), /** * test */ - TEST(SystemEnvironmentNameConst.TEST, "测试环境"), + TEST(EnvConst.TEST, "测试环境"), /** * pre */ - PRE(SystemEnvironmentNameConst.PRE, "预发布环境"), + PRE(EnvConst.PRE, "预发布环境"), /** * prod */ - PROD(SystemEnvironmentNameConst.PROD, "生产环境"); + PROD(EnvConst.PROD, "生产环境"); private final String value; private final String desc; - public static final class SystemEnvironmentNameConst { + public static final class EnvConst { public static final String DEV = "dev"; public static final String TEST = "test"; public static final String PRE = "pre"; diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/UserTypeEnum.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/UserTypeEnum.java index c34670b9..ff95a981 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/UserTypeEnum.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/enumeration/UserTypeEnum.java @@ -1,5 +1,8 @@ package net.lab1024.sa.common.common.enumeration; +import lombok.AllArgsConstructor; +import lombok.Getter; + /** * 用户类型 * @@ -9,29 +12,16 @@ package net.lab1024.sa.common.common.enumeration; * @Email lab1024@163.com * @Copyright 1024创新实验室 ( https://1024lab.net ),2012-2022 */ +@Getter +@AllArgsConstructor public enum UserTypeEnum implements BaseEnum { /** * 管理端 员工用户 */ - ADMIN_EMPLOYEE(1, "员工"); + ADMIN_EMPLOYEE(1, "管理端-员工"); - private Integer type; + private final Integer value; - private String desc; - - UserTypeEnum(Integer type, String desc) { - this.type = type; - this.desc = desc; - } - - @Override - public Integer getValue() { - return type; - } - - @Override - public String getDesc() { - return desc; - } + private final String desc; } diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/interceptor/AbstractInterceptor.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/interceptor/AbstractInterceptor.java index 3d0bb442..9abc3465 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/interceptor/AbstractInterceptor.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/interceptor/AbstractInterceptor.java @@ -1,14 +1,24 @@ package net.lab1024.sa.common.common.interceptor; import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.extra.servlet.ServletUtil; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import net.lab1024.sa.common.common.annoation.NoNeedLogin; import net.lab1024.sa.common.common.code.UserErrorCode; +import net.lab1024.sa.common.common.constant.RequestHeaderConst; import net.lab1024.sa.common.common.domain.RequestUser; import net.lab1024.sa.common.common.domain.ResponseDTO; +import net.lab1024.sa.common.common.domain.SystemEnv; +import net.lab1024.sa.common.common.enumeration.SystemEnvEnum; +import net.lab1024.sa.common.common.enumeration.UserTypeEnum; import net.lab1024.sa.common.common.util.SmartRequestUtil; +import net.lab1024.sa.common.module.support.token.TokenService; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -29,17 +39,21 @@ import java.util.List; * @date 2023-07-12 21:56:14 */ public abstract class AbstractInterceptor implements HandlerInterceptor { - /** - * 校验 token - */ - public abstract void checkSaToken(); + + @Autowired + private SystemEnv systemEnv; /** - * Token 获取当前请求用户信息 + * 校验 token * - * @return + * @param userId */ - public abstract RequestUser getRequestUser(); + public abstract RequestUser getDevUser(Long userId); + + /** + * 校验 当前服务用户类型 + */ + public abstract UserTypeEnum getUserType(); /** * 拦截路径 @@ -83,8 +97,8 @@ public abstract class AbstractInterceptor implements HandlerInterceptor { if (!isHandler) { return true; } - // 校验 token 获取当前请求用户信息 - ResponseDTO res = this.checkTokenAndGetUser(); + // 校验 token + ResponseDTO res = this.checkTokenAndGetUser(request); if (res.getOk()) { SmartRequestUtil.setUser(res.getData()); return true; @@ -99,7 +113,6 @@ public abstract class AbstractInterceptor implements HandlerInterceptor { } /** - * 校验 sa token * 判断 sa-token 未登录场景值 * 自己根据业务在下面 switch 添加分支判断 * NotLoginException.NOT_TOKEN 无token @@ -111,13 +124,28 @@ public abstract class AbstractInterceptor implements HandlerInterceptor { *

* ps :之所以没有在全局异常里处理 是因为后续还有操作 */ - public ResponseDTO checkTokenAndGetUser() { + public ResponseDTO checkTokenAndGetUser(HttpServletRequest request) { + /** + * 处理【非生产环境】的测试 token ,便于开发调试 + * 如不需要 可以删除此段判断代码 + */ + if (SystemEnvEnum.PROD != systemEnv.getCurrentEnv()) { + String tokenValue = StpUtil.getTokenValue(); + if (NumberUtils.isDigits(tokenValue)) { + RequestUser user = this.getDevUser(NumberUtils.createLong(tokenValue)); + this.handleRequestIpAndAgent(user, request); + // sa token 登录身份临时切换 + StpUtil.switchTo(TokenService.generateLoginId(user.getUserId(), user.getUserType())); + return ResponseDTO.ok(user); + } + } + try { /** - * sa-token 会从当前请求header or body 中获取token + * sa-token 会从当前请求 header or body 中获取token * 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException` */ - this.checkSaToken(); + StpUtil.checkLogin(); } catch (NotLoginException e) { switch (e.getType()) { case NotLoginException.BE_REPLACED: @@ -129,8 +157,13 @@ public abstract class AbstractInterceptor implements HandlerInterceptor { return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID); } } - RequestUser requestUser = this.getRequestUser(); - return ResponseDTO.ok(requestUser); + // 校验token的用户类型 + UserTypeEnum systemUserTypeEnum = this.getUserType(); + RequestUser user = this.buildCurrentUser(request); + if (null == user || systemUserTypeEnum != user.getUserType()) { + return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID); + } + return ResponseDTO.ok(user); } /** @@ -147,8 +180,35 @@ public abstract class AbstractInterceptor implements HandlerInterceptor { response.flushBuffer(); } - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { - SmartRequestUtil.remove(); + /** + * build 当前请求用户 + * + * @param request + * @return + */ + public RequestUser buildCurrentUser(HttpServletRequest request) { + // 获取额外数据 + SaSession session = StpUtil.getSession(); + UserTypeEnum userTypeEnum = (UserTypeEnum) session.get(TokenService.EXTRA_KEY_USER_TYPE); + String userName = session.getString(TokenService.EXTRA_KEY_USER_NAME); + + // 当前请求对象 + RequestUser user = new RequestUser(); + user.setUserId(TokenService.getUserId((String) StpUtil.getLoginId())); + user.setUserName(userName); + user.setUserType(userTypeEnum); + this.handleRequestIpAndAgent(user, request); + return user; + } + + /** + * 设置 当前请求ip agent + * + * @param requestUser + * @param request + */ + private void handleRequestIpAndAgent(RequestUser requestUser, HttpServletRequest request) { + requestUser.setUserAgent(ServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT)); + requestUser.setIp(ServletUtil.getClientIP(request)); } } diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java index 0e22b630..5e139e25 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java @@ -1,6 +1,7 @@ package net.lab1024.sa.common.common.util; -import lombok.extern.slf4j.Slf4j; +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaStorage; import net.lab1024.sa.common.common.domain.RequestUser; /** @@ -12,26 +13,28 @@ import net.lab1024.sa.common.common.domain.RequestUser; * @Email lab1024@163.com * @Copyright 1024创新实验室 ( https://1024lab.net ) */ -@Slf4j public class SmartRequestUtil { - private static final ThreadLocal LOCAL = new ThreadLocal<>(); + private static final String STORAGE_KEY = "user"; - public static void setUser(RequestUser requestUser) { - LOCAL.set(requestUser); + public static void setUser(RequestUser user) { + SaStorage storage = SaHolder.getStorage(); + storage.set(STORAGE_KEY, user); } + /** + * 获取 当前 token 请求用户 + * + * @return + */ public static RequestUser getUser() { - return LOCAL.get(); + SaStorage storage = SaHolder.getStorage(); + return storage.getModel(STORAGE_KEY, RequestUser.class); } public static Long getUserId() { - RequestUser requestUser = getUser(); - return null == requestUser ? null : requestUser.getUserId(); - } - - public static void remove() { - LOCAL.remove(); + RequestUser user = getUser(); + return null != user ? user.getUserId() : null; } diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java index c2bfb480..494e6f8d 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java @@ -1,6 +1,7 @@ package net.lab1024.sa.common.config; import cn.dev33.satoken.interceptor.SaInterceptor; +import com.google.common.collect.Sets; import net.lab1024.sa.common.common.interceptor.AbstractInterceptor; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -10,7 +11,9 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * web相关配置 @@ -33,8 +36,10 @@ public class MvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 先注册 登录拦截器 + Set ignoreUrlSet = Sets.newHashSet(); if (CollectionUtils.isNotEmpty(interceptorList)) { interceptorList.forEach(e -> { + ignoreUrlSet.addAll(e.getIgnoreUrlList()); registry.addInterceptor(e).addPathPatterns(e.pathPatterns()).excludePathPatterns(e.getIgnoreUrlList()); }); } @@ -42,7 +47,7 @@ public class MvcConfig implements WebMvcConfigurer { // 后注册 sa-token 权限拦截器 不需要可以删除 if (CollectionUtils.isNotEmpty(saInterceptorList)) { saInterceptorList.forEach(i -> { - registry.addInterceptor(i).addPathPatterns("/**"); + registry.addInterceptor(i).addPathPatterns("/**").excludePathPatterns(new ArrayList<>(ignoreUrlSet)); }); } } diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java index bf0a0940..60cff6a0 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java @@ -198,7 +198,7 @@ public class SwaggerConfig implements EnvironmentAware, BeanDefinitionRegistryPo Parameter token = new ParameterBuilder().name(RequestHeaderConst.TOKEN) .description("token") .modelRef(new ModelRef("string")) - .parameterType("header").defaultValue("1") + .parameterType("header").defaultValue("0") .required(false) .build(); return Lists.newArrayList(token); diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java index 8de7ed91..deea8494 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java @@ -34,8 +34,6 @@ public class UrlConfig { @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; - public static List AUTH_URL_LIST = Lists.newArrayList(); - /** * 获取每个方法的请求路径 * @@ -81,8 +79,6 @@ public class UrlConfig { Set urlSet = entry.getValue(); List requestUrlList = this.buildRequestUrl(method, urlSet); authUrlList.addAll(requestUrlList); - - AUTH_URL_LIST.addAll(urlSet); } log.info("需要权限校验的URL:{}", authUrlList.stream().map(RequestUrlVO::getUrl).collect(Collectors.toList())); return authUrlList; diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/satoken/SaTokenCommonConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/satoken/SaTokenCommonConfig.java deleted file mode 100644 index f229d8f0..00000000 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/satoken/SaTokenCommonConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.lab1024.sa.common.config.satoken; - -import cn.dev33.satoken.jwt.StpLogicJwtForSimple; -import cn.dev33.satoken.stp.StpLogic; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * sa token 配置 - * - * @author: listen - * @date: 2023/7/12 20:46 - */ -@Configuration -public class SaTokenCommonConfig { - - /** - * 整合 jwt - * - * @return - * @see https://sa-token.cc/doc.html#/plugin/jwt-extend - */ - @Bean - public StpLogic getStpLogicJwt() { - // Simple 简单模式 - return new StpLogicJwtForSimple(); - } - -} diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java index 4847e0de..07b3acea 100644 --- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java +++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java @@ -1,5 +1,6 @@ package net.lab1024.sa.common.module.support.token; +import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; import net.lab1024.sa.common.common.constant.StringConst; @@ -37,31 +38,34 @@ public class TokenService { /** * 设置登录模式参数 - * 具体参数 @see SaLoginModel 属性 + * 具体参数 {@link SaLoginModel } 属性 * 已经写的挺清楚的了 */ SaLoginModel loginModel = new SaLoginModel(); // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型 loginModel.setDevice(String.valueOf(loginDeviceEnum.getDesc())); - // 扩展参数 只在 jwt 模式下 有效 - loginModel.setExtra(EXTRA_KEY_USER_NAME, userName); - loginModel.setExtra(EXTRA_KEY_USER_TYPE, userTypeEnum.getValue()); + // 登录 String loginId = generateLoginId(userId, userTypeEnum); StpUtil.login(loginId, loginModel); + + // 扩展参数 放入会话中 redis session + SaSession session = StpUtil.getSession(); + session.set(EXTRA_KEY_USER_NAME, userName); + session.set(EXTRA_KEY_USER_TYPE, userTypeEnum); return StpUtil.getTokenValue(); } public static String generateLoginId(Long userId, UserTypeEnum userType) { - return userType.getValue() + StringConst.HORIZONTAL + userId; + return userType.getValue() + StringConst.COLON + userId; } public static Long getUserId(String loginId) { - return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.HORIZONTAL) + 1)); + return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.COLON) + 1)); } public static Integer getUserType(String loginId) { - return Integer.valueOf(loginId.substring(0, loginId.indexOf(StringConst.HORIZONTAL))); + return Integer.valueOf(loginId.substring(0, loginId.indexOf(StringConst.COLON))); } /**