You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:54:19