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

前端Axios调用SpringBoot接口出现403权限问题求助

问题排查与解决方案

核心问题1:Axios请求头拼写错误

前端图书列表组件的请求中,Headers是大写开头,但Axios的配置项要求小写的headers,这直接导致Authorization头没有被正确携带到后端,触发403权限验证失败。

修正后的前端请求代码:

export default function Books(){
    const [books, setBooks] = useState([]);
    const [page, setPage] = useState(0);
    
    const username = localStorage.getItem('username');
    const access_token = localStorage.getItem('accessToken');

    const history = useHistory();

    useEffect(() => {
        // 修正:Headers → headers
        api.get('api/book/v1', {
            headers: {
                Authorization: `Bearer ${access_token}`
            },
            params: {
                page: 0,
                size: 10,
                direction: 'asc'
            }
        }).then(response => {
            setBooks(response.data._embedded.bookVOList)
        }).catch(err => {
            console.error('请求失败:', err);
        })
    }, []) // 补充空依赖数组,避免useEffect无限执行
}

核心问题2:前后端端口不匹配

你描述后端运行在localhost:8000,但Axios的baseURL配置的是http://localhost:8080,这会导致请求发送到错误端口。务必确认:

  • 后端启动日志显示的实际端口
  • 若后端确实是8000,修改Axios配置:
const api = axios.create({
    baseURL: 'http://localhost:8000'
});

后端配置补充检查

1. 验证JwtConfigurer有效性

确保JwtConfigurer正确实现token解析逻辑,比如从请求头提取Authorization信息、验证签名、解析用户身份,核心实现示例:

public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
    private TokenProvider tokenProvider;

    public JwtConfigurer(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        JwtTokenFilter customFilter = new JwtTokenFilter(tokenProvider);
        http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

// JwtTokenFilter核心逻辑
public class JwtTokenFilter extends OncePerRequestFilter {
    private TokenProvider tokenProvider;

    public JwtTokenFilter(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = resolveToken(request);
        if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
            Authentication authentication = tokenProvider.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }

    private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

2. 简化跨域配置避免冲突

由于SecurityConfig中已启用.cors(),可直接在Security内配置跨域,移除WebConfig的跨域配置防止冲突:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic().disable()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
                .and()
                    .authorizeRequests()
                    .antMatchers("/auth/signin", "/auth/refresh", "/api-docs/**", "/swagger-ui.html**").permitAll()
                    .antMatchers("/api/**").authenticated()
                    .antMatchers("/users").denyAll()
                .and()
                    .cors().configurationSource(corsConfigurationSource())
                .and()
                .apply(new JwtConfigurer(tokenProvider));
    }

    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

额外调试建议

  • 打开浏览器开发者工具(F12),查看Network标签下的/api/book/v1请求,确认Request Headers中是否存在Authorization: Bearer xxx
  • 后端在JwtTokenFilter中添加日志,打印提取到的token,确认是否正确接收
  • 用JWT解析工具检查accessToken的过期时间、签名、用户权限等信息

内容的提问来源于stack exchange,提问作者João Vitor Menezes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:55:19