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

Spring Boot 3.0+Spring Security JWT请求Access Denied问题排查

JWT认证通过但接口返回Access Denied排查方案

核心问题

注册、登录获取JWT Token流程正常,但携带Token请求带有@PreAuthorize("hasRole('ROLE_USER')")注解的接口时,返回Access Denied错误。

排查步骤及解决方法

1. 检查JWT Token角色格式与权限注入逻辑

Spring Security的hasRole()方法默认会自动为角色名称添加ROLE_前缀,需确保Token中的角色与注解规则匹配:

  • 查看JwtUtils生成Token时,存入的角色名称是USER还是ROLE_USER:
    • 若Token中存的是USER,则注解应改为@PreAuthorize("hasRole('USER')"),或在注入权限时手动添加ROLE_前缀;
    • 若注解用hasRole('ROLE_USER'),则生成Token和解析时需确保角色名称包含ROLE_前缀。
  • 检查AuthTokenFilter中解析Token后构建Authentication对象的权限赋值:
    // 正确示例:确保权限带有ROLE_前缀(适配hasRole('ROLE_USER')注解)
    List<GrantedAuthority> authorities = userRoles.stream()
        .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
        .collect(Collectors.toList());
    UsernamePasswordAuthenticationToken authentication = 
        new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    

2. 验证Security配置类关键项

  • 确认已开启方法级安全:在WebSecurityConfig类上添加@EnableGlobalMethodSecurity(prePostEnabled = true),否则@PreAuthorize注解不会生效。
  • 确认JWT过滤器位置正确:需将AuthTokenFilter添加到UsernamePasswordAuthenticationFilter之前,确保请求先经过JWT解析:
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/auth/**").permitAll() // 放行登录注册接口
            .anyRequest().authenticated()
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        // 注入JWT过滤器,位置必须在UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(authTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }
    

3. 检查Token携带方式

  • 确认Postman请求头格式正确:使用Authorization: Bearer <你的Token>,注意Bearer后必须有一个空格,且Token无多余空格或换行。
  • 若项目自定义了Token请求头(如X-Auth-Token),需确保Postman使用的头名称与AuthTokenFilter中解析的头一致。

4. 验证Token有效性与解析逻辑

  • 用jwt.io解析Token,检查:
    • exp字段是否未过期;
    • 自定义角色字段(如roles)是否包含预期的角色值;
    • 签名是否有效(确保JwtUtils生成和解析用的是同一密钥)。
  • 调试AuthTokenFilter,确认Token解析成功,且SecurityContextHolder中正确存入了带有对应权限的Authentication对象。

5. 调整权限匹配规则

  • 若使用hasRole(),避免重复添加ROLE_前缀(比如hasRole('ROLE_USER')是正确的,不要写成hasRole('ROLE_ROLE_USER'));
  • 可尝试用hasAuthority('ROLE_USER')替代hasRole(),hasAuthority()会严格匹配权限字符串,无需自动添加前缀。

内容的提问来源于stack exchange,提问作者Smetana Po Aktsii

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:58:07