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

Spring Boot Security+JWT:Postman请求401但Swagger正常

问题排查与解决方案

1. 检查Postman请求头配置

  • 确认Authorization头格式必须为 Bearer <你的JWT Token>,注意Bearer后有且仅有一个空格,且首字母为大写。常见错误包括直接放置token、写成小写bearer,这会导致getJWTFromRequest方法无法正确提取token,最终触发认证失败。
  • 建议直接使用Postman的Authorization标签下的Bearer Token类型,自动生成合规的请求头。

2. 验证JWT Token有效性

  • 确保Postman使用的token与Swagger中正常工作的token一致,或为刚生成的未过期token。可通过jwt.io在线解析token,检查:
    • exp字段是否已过期
    • sub字段是否为系统中存在的用户邮箱(你的UserPrincipal以邮箱作为用户名)
  • 确认项目配置文件中的app.jwt-secret密钥,在Postman请求环境与Swagger运行环境中完全一致,密钥不匹配会直接导致token验证失败。

3. 核对请求路径匹配规则

  • 你的SecurityConfig中配置了/seans/**允许无权限访问,需确认Postman请求的完整路径是否匹配该规则:
    • 若接口所在控制器带有@RequestMapping("/seans"),则完整路径为/seans/save,符合规则;
    • 若控制器路径为/api/v1/seans,则完整路径为/api/v1/seans/save,不在/seans/**范围内,会触发认证要求,但Swagger可能自动拼接了正确路径所以正常。

4. 排查JWT过滤器执行逻辑

  • 在JwtAuthenticationFilter的doFilterInternal方法中添加日志,打印关键步骤,确认token提取、验证及用户加载流程:
    logger.info("Received Authorization header: {}", request.getHeader("Authorization"));
    String token = getJWTFromRequest(request);
    logger.info("Extracted JWT token: {}", token);
    if (StringUtils.hasText(token) && jwtUtil.validateJwtToken(token)) {
        logger.info("Token is valid, username: {}", jwtUtil.getUsernameFromJwtToken(token));
        // 后续逻辑日志
    } else {
        logger.info("Token is invalid or empty");
    }
    
  • 确认JwtAuthenticationFilter的jwtUtil和userDetailsService是否被正确注入,可在过滤器构造函数中添加初始化日志验证。

5. 权限配置确认

  • 虽然接口未添加方法级权限注解,但@EnableMethodSecurity已启用,需确保无全局权限规则冲突。另外检查UserPrincipal的getAuthorities方法,确认角色转换是否正确(若数据库角色名称未带ROLE_前缀,需手动添加,否则可能导致后续权限校验失败,但不会直接触发401)。

6. 跨域配置补全(针对前端场景)

  • 若前端请求也遇到类似问题,需显式配置CORS允许Authorization头:
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*")); // 根据实际业务设置允许的源
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
    
    然后在filterChain中替换为http.cors(cors -> cors.configurationSource(corsConfigurationSource()))。

内容的提问来源于stack exchange,提问作者anar1501

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:37:04