SpringBoot:如何将HttpOnly Cookie请求传递至Controller的whoAmI接口
解决方案
首先明确:过滤器本身就会通过filterChain.doFilter(request, response)将请求传递到控制器,你的核心需求是把原本在过滤器中的JWT认证逻辑迁移到whoAmI接口,同时实现页面刷新后获取用户信息的功能,具体步骤如下:
1. 调整原过滤器逻辑
如果你想完全将认证逻辑移到控制器,可以修改AuthTokenFilter,去掉其中的认证代码,只保留请求传递的逻辑:
public class AuthTokenFilter extends OncePerRequestFilter { private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { // 移除原认证逻辑,仅传递请求到控制器 } catch (Exception e) { logger.error("Filter error: {}", e); } filterChain.doFilter(request, response); } }
或者直接从Spring Security的过滤器链中移除该过滤器(比如注释掉注册该过滤器的@Bean代码)。
2. 完善whoAmI接口逻辑
在控制器的whoAmI方法中实现原本过滤器的认证逻辑,并返回用户信息:
@Autowired private JwtUtils jwtUtils; @Autowired private MyUserDetailsService userDetailsService; @Autowired private UserService userService; private static final Logger logger = LoggerFactory.getLogger(AuthController.class); @GetMapping("/whoAmI") public ResponseEntity<?> whoAmI(HttpServletRequest request) { try { // 从Cookie中解析JWT String jwt = jwtUtils.getJwtFromCookies(request); if (jwt != null && jwtUtils.validateJwtToken(jwt)) { // 从JWT中获取用户邮箱 String email = jwtUtils.getEmailFromJwtToken(jwt); // 加载用户详情 UserDetails userDetails = userDetailsService.loadUserByUsername(email); // 设置安全上下文,确保后续接口能获取认证信息 UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); // 查询并返回用户Profile Object userProfile = userService.findUserProfileUserByEmail(userDetails.getEmail()); return ResponseEntity.ok(userProfile); } // JWT无效或不存在,返回未认证状态 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("未找到有效登录凭证"); } catch (Exception e) { logger.error("获取用户信息失败: {}", e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取用户信息出错"); } }
3. 前端配合调整
页面刷新后,前端需要主动调用/whoAmI接口,将返回的userProfile存入前端状态(比如Vuex、Redux或内存状态),这样就能恢复登录状态的用户信息。
注意事项
如果你的应用还有其他需要认证的接口,这种仅在whoAmI处理认证的方式会导致其他接口在调用whoAmI前无法获取用户信息,此时更推荐保留过滤器的认证逻辑,whoAmI仅负责从SecurityContext中获取用户信息并返回:
@GetMapping("/whoAmI") public ResponseEntity<?> whoAmI() { // 直接从安全上下文获取已认证的用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { UserDetails userDetails = (UserDetails) authentication.getPrincipal(); Object userProfile = userService.findUserProfileUserByEmail(userDetails.getEmail()); return ResponseEntity.ok(userProfile); } return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("未登录"); }
这种方式下,过滤器负责所有请求的认证,whoAmI仅做数据返回,更符合Spring Security的设计规范,也能保证所有接口的认证一致性。
内容的提问来源于stack exchange,提问作者ABpositive
相关产品推荐
相关产品推荐

