diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyi/auth/controller/UserController.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyi/auth/controller/UserController.java index cd29715..d38f13b 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyi/auth/controller/UserController.java +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyi/auth/controller/UserController.java @@ -3,10 +3,7 @@ package top.crushtj.xiaoyi.auth.controller; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog; import top.crushtj.framework.common.response.Response; import top.crushtj.xiaoyi.auth.model.vo.user.UserLoginReqVO; @@ -36,7 +33,7 @@ public class UserController { @PostMapping("/logout") @ApiOperationLog(description = "用户登出") - public Response logout() { + public Response logout(@RequestHeader("userId") String userId) { // todo 实现用户登出逻辑 return Response.success(); } diff --git a/xiaoyi-auth/src/main/resources/config/application.yml b/xiaoyi-auth/src/main/resources/config/application.yml index 6a08563..1078c9f 100644 --- a/xiaoyi-auth/src/main/resources/config/application.yml +++ b/xiaoyi-auth/src/main/resources/config/application.yml @@ -14,6 +14,7 @@ sa-token: token-prefix: Bearer # token 有效期(单位:秒) 默认30天,-1 代表永久有效 timeout: 2592000 +# timeout: 60 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 active-timeout: -1 # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java index 2dd8cbd..76c06c1 100644 --- a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java @@ -1,5 +1,8 @@ package top.crushtj.xiaoyi.gateway.auth; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.exception.NotPermissionException; +import cn.dev33.satoken.exception.NotRoleException; import cn.dev33.satoken.reactor.filter.SaReactorFilter; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; @@ -30,7 +33,7 @@ public class SaTokenConfigure { .notMatch("/auth/verification/code/send") // 排除验证码发送接口 .check(r -> StpUtil.checkLogin()) // 校验是否登录 ; - SaRouter.match("/auth/**", r -> StpUtil.checkPermission("user")); +// SaRouter.match("/auth/user/logout", r -> StpUtil.checkPermission("user")); // 权限认证 -- 不同模块, 校验不同权限 // SaRouter.match("/user/**", r -> StpUtil.checkPermission("user")); // SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin")); @@ -38,6 +41,15 @@ public class SaTokenConfigure { // SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders")); // 更多匹配 ... */ + }) + .setError(e -> { + if (e instanceof NotLoginException) { // 未登录异常 + throw new NotLoginException(e.getMessage(), null, null); + } else if (e instanceof NotPermissionException || e instanceof NotRoleException) { // 权限不足,或不具备角色,统一抛出权限不足异常 + throw new NotPermissionException(e.getMessage()); + } else { // 其他异常,则抛出一个运行时异常 + throw new RuntimeException(e.getMessage()); + } }); } } diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java index 3a9a985..6b35435 100644 --- a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java @@ -1,5 +1,7 @@ package top.crushtj.xiaoyi.gateway.exception; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.exception.NotPermissionException; import cn.dev33.satoken.exception.SaTokenException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Resource; @@ -43,9 +45,17 @@ public class GlobalExceptionHandler implements ErrorWebExceptionHandler { if (ex instanceof SaTokenException) { // Sa-Token 异常 // 权限认证失败时,设置 401 状态码 response.setStatusCode(HttpStatus.UNAUTHORIZED); - // 构建响应结果 - result = Response.failure(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), - ResponseCodeEnum.UNAUTHORIZED.getErrorMessage()); + if (ex instanceof NotLoginException){ + // 构建响应结果 + result = Response.failure(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), + ex.getMessage()); + }else if (ex instanceof NotPermissionException) { + result = Response.failure(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), + ResponseCodeEnum.UNAUTHORIZED.getErrorMessage()); + } else { + result = Response.failure(ResponseCodeEnum.SYSTEM_ERROR); + } + } else { // 其他异常,则统一提示 “系统繁忙” 错误 result = Response.failure(ResponseCodeEnum.SYSTEM_ERROR); } diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/filter/AddUserId2HeaderFilter.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/filter/AddUserId2HeaderFilter.java new file mode 100644 index 0000000..d3d602b --- /dev/null +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/filter/AddUserId2HeaderFilter.java @@ -0,0 +1,40 @@ +package top.crushtj.xiaoyi.gateway.filter; + +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * @author ayi + * @version V1.0 + * @title AddUserId2HeaderFilter + * @date 2026/2/4 15:28 + * @description 添加用户ID到请求头过滤器 + */ + +@Slf4j +@Component +public class AddUserId2HeaderFilter implements GlobalFilter { + + private static final String HEADER_USER_ID = "userId"; + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + Long userId = null; + try { + userId = StpUtil.getLoginIdAsLong(); + } catch (Exception e) { + return chain.filter(exchange); + } + Long finalUserId = userId; + ServerWebExchange newExchange = exchange.mutate() + .request(builder -> builder.header(HEADER_USER_ID, String.valueOf(finalUserId))) + .build(); + + return chain.filter(newExchange); + } +} diff --git a/xiaoyi-gateway/src/main/resources/application.yml b/xiaoyi-gateway/src/main/resources/application.yml index 6246714..38a7a61 100644 --- a/xiaoyi-gateway/src/main/resources/application.yml +++ b/xiaoyi-gateway/src/main/resources/application.yml @@ -32,6 +32,7 @@ sa-token: token-prefix: Bearer # token 有效期(单位:秒) 默认30天,-1 代表永久有效 timeout: 2592000 +# timeout: 60 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 active-timeout: -1 # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)