diff --git a/src/main/java/com/label/common/context/CompanyContext.java b/src/main/java/com/label/common/context/CompanyContext.java index f46bf69..6381428 100644 --- a/src/main/java/com/label/common/context/CompanyContext.java +++ b/src/main/java/com/label/common/context/CompanyContext.java @@ -1,13 +1,16 @@ package com.label.common.context; public class CompanyContext { - private static final ThreadLocal COMPANY_ID = new ThreadLocal<>(); + private static final ThreadLocal COMPANY_ID = new ThreadLocal<>().withInitial(() -> -1L); public static void set(Long companyId) { COMPANY_ID.set(companyId); } public static Long get() { + if (COMPANY_ID.get() == null) { + throw new IllegalStateException("Company ID not set"); + } return COMPANY_ID.get(); } diff --git a/src/main/java/com/label/common/shiro/TokenFilter.java b/src/main/java/com/label/common/shiro/TokenFilter.java index dfaa48d..558629f 100644 --- a/src/main/java/com/label/common/shiro/TokenFilter.java +++ b/src/main/java/com/label/common/shiro/TokenFilter.java @@ -67,12 +67,12 @@ public class TokenFilter extends OncePerRequestFilter { || path.equals("/api/auth/login") || path.equals("/api/video/callback") || path.startsWith("/swagger-ui") - || path.startsWith("/v3/api-docs"); // AI 服务内部回调,不走用户 Token 认证 + || path.startsWith("/v3/api-docs"); // AI 服务内部回调,不走用户 Token 认证 } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + FilterChain filterChain) throws ServletException, IOException { try { if (!authEnabled) { TokenPrincipal principal = new TokenPrincipal( @@ -85,12 +85,17 @@ public class TokenFilter extends OncePerRequestFilter { } String authHeader = request.getHeader("Authorization"); - if (authHeader == null || !authHeader.startsWith("Bearer ")) { + if (authHeader == null || !authHeader.toLowerCase().startsWith("bearer ")) { writeUnauthorized(response, "缺少或无效的认证令牌"); return; } - - String token = authHeader.substring(7).trim(); + String[] parts = authHeader.split("\\s+"); + if (parts.length != 2 || !"Bearer".equalsIgnoreCase(parts[0])) { + writeUnauthorized(response, "无效的认证格式"); + return; + } + String token = parts[1]; + //String token = authHeader.substring(7).trim(); Map tokenData = redisService.hGetAll(RedisKeyManager.tokenKey(token)); if (tokenData == null || tokenData.isEmpty()) { diff --git a/src/main/java/com/label/module/user/controller/UserController.java b/src/main/java/com/label/module/user/controller/UserController.java index afed456..c31b9eb 100644 --- a/src/main/java/com/label/module/user/controller/UserController.java +++ b/src/main/java/com/label/module/user/controller/UserController.java @@ -1,18 +1,27 @@ package com.label.module.user.controller; +import java.util.Map; + +import org.apache.shiro.authz.annotation.RequiresRoles; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + import com.label.common.result.PageResult; import com.label.common.result.Result; import com.label.common.shiro.TokenPrincipal; import com.label.module.user.entity.SysUser; import com.label.module.user.service.UserService; + import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.apache.shiro.authz.annotation.RequiresRoles; -import org.springframework.web.bind.annotation.*; - -import java.util.Map; /** * 用户管理接口(5 个端点,全部 ADMIN 权限)。 @@ -41,7 +50,7 @@ public class UserController { @PostMapping @RequiresRoles("ADMIN") public Result createUser(@RequestBody Map body, - HttpServletRequest request) { + HttpServletRequest request) { return Result.success(userService.createUser( body.get("username"), body.get("password"), @@ -55,8 +64,8 @@ public class UserController { @PutMapping("/{id}") @RequiresRoles("ADMIN") public Result updateUser(@PathVariable Long id, - @RequestBody Map body, - HttpServletRequest request) { + @RequestBody Map body, + HttpServletRequest request) { return Result.success(userService.updateUser( id, body.get("realName"), @@ -65,23 +74,23 @@ public class UserController { } /** PUT /api/users/{id}/status — 变更用户状态 */ - @Operation(summary = "变更用户状态") + @Operation(summary = "变更用户状态", description = "status:ACTIVE、DISABLED") @PutMapping("/{id}/status") @RequiresRoles("ADMIN") public Result updateStatus(@PathVariable Long id, - @RequestBody Map body, - HttpServletRequest request) { + @RequestBody Map body, + HttpServletRequest request) { userService.updateStatus(id, body.get("status"), principal(request)); return Result.success(null); } /** PUT /api/users/{id}/role — 变更用户角色 */ - @Operation(summary = "变更用户角色") + @Operation(summary = "变更用户角色", description = "role:ADMIN、UPLOADER、VIEWER") @PutMapping("/{id}/role") @RequiresRoles("ADMIN") public Result updateRole(@PathVariable Long id, - @RequestBody Map body, - HttpServletRequest request) { + @RequestBody Map body, + HttpServletRequest request) { userService.updateRole(id, body.get("role"), principal(request)); return Result.success(null); } diff --git a/src/main/java/com/label/module/user/service/UserService.java b/src/main/java/com/label/module/user/service/UserService.java index 5a53876..0f0edd8 100644 --- a/src/main/java/com/label/module/user/service/UserService.java +++ b/src/main/java/com/label/module/user/service/UserService.java @@ -1,5 +1,13 @@ package com.label.module.user.service; +import java.util.List; +import java.util.Set; + +import org.springframework.http.HttpStatus; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.label.common.exception.BusinessException; @@ -9,16 +17,9 @@ import com.label.common.result.PageResult; import com.label.common.shiro.TokenPrincipal; import com.label.module.user.entity.SysUser; import com.label.module.user.mapper.SysUserMapper; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Map; -import java.util.Set; /** * 用户管理服务(ADMIN 专属)。 @@ -52,8 +53,8 @@ public class UserService { */ @Transactional public SysUser createUser(String username, String password, - String realName, String role, - TokenPrincipal principal) { + String realName, String role, + TokenPrincipal principal) { // 校验用户名唯一性 SysUser existing = userMapper.selectByCompanyAndUsername(principal.getCompanyId(), username); if (existing != null) { @@ -83,7 +84,7 @@ public class UserService { */ @Transactional public SysUser updateUser(Long userId, String realName, String password, - TokenPrincipal principal) { + TokenPrincipal principal) { SysUser user = getExistingUser(userId, principal.getCompanyId()); LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper() @@ -127,8 +128,7 @@ public class UserService { // 2. 更新所有活跃 Token 中的 role 字段(立即生效,无需重新登录) Set tokens = redisService.sMembers(RedisKeyManager.userSessionsKey(userId)); - tokens.forEach(token -> - redisService.hPut(RedisKeyManager.tokenKey(token), "role", newRole)); + tokens.forEach(token -> redisService.hPut(RedisKeyManager.tokenKey(token), "role", newRole)); // 3. 删除权限缓存(如 Shiro 缓存存在) redisService.delete(RedisKeyManager.userPermKey(userId));