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

Spring Boot+AngularJS 1.6集成CSRF保护遇未授权问题求助

Troubleshooting Your Spring Security CSRF + AngularJS Authorization Issue

Let’s walk through the potential gaps in your setup that could be causing the unauthorized status when sending requests. You’ve got the core CSRF pieces in place, but there are a few subtle configuration details and workflow checks to verify:

1. Fix Spring Security Configuration Order & Duplicate Settings

Looking at your code, you’ve got duplicate exceptionHandling() configurations and a slightly disjointed chain that might be causing unexpected behavior:

  • You first configure an authenticationEntryPoint early in the chain, then later redefine http.exceptionHandling() entirely. This overwrites your initial entry point setup, leading to inconsistent error handling for unauthorized requests.
  • Spreading the configuration across multiple http. calls makes it harder to track the execution flow.

Here’s a cleaned-up, consolidated version of your configuration with a logical flow:

@Override
protected void configure(HttpSecurity http) throws Exception {
    System.out.println("Setting up Security configuration");
    http
        // CSRF configuration first
        .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
        // Custom filter placement
        .addFilterBefore(new AlreadyConnectedFilter(), UsernamePasswordAuthenticationFilter.class)
        .authenticationProvider(authProvider)
        // Form login setup
        .formLogin()
            .permitAll()
            .loginProcessingUrl("/login")
            .usernameParameter("username")
            .passwordParameter("password")
            .successHandler(authSuccessHandler)
            .failureHandler(authFailureHandler)
            .and()
        // Logout configuration
        .logout()
            .permitAll()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "DELETE"))
            .logoutSuccessHandler(logoutSuccessHandler)
            .and()
        // Session management
        .sessionManagement()
            .maximumSessions(-1)
            .expiredSessionStrategy(new CustomSessionInformationExpiredStrategy())
            .sessionRegistry(sessionRegistry())
            .and()
        // HTTP Basic auth
        .httpBasic()
            .and()
        // Authorization rules
        .authorizeRequests()
            .anyRequest().permitAll()
            .and()
        // Consolidated exception handling
        .exceptionHandling()
            .accessDeniedHandler((request, response, accessDeniedException) -> {
                response.setContentType("application/json");
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                Map<String, Object> contentToSend = new HashMap<>();
                contentToSend.put("message", accessDeniedException.getMessage());
                contentToSend.put("errors", new ArrayList<>());
                contentToSend.put("status", response.getStatus());
                PrintWriter writer = response.getWriter();
                writer.write(new ObjectMapper().writeValueAsString(contentToSend));
                writer.flush();
            })
            .authenticationEntryPoint((request, response, authException) -> {
                response.setContentType("application/json");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                Map<String, Object> contentToSend = new HashMap<>();
                contentToSend.put("message", authException.getMessage());
                contentToSend.put("errors", new ArrayList<>());
                contentToSend.put("status", response.getStatus());
                PrintWriter writer = response.getWriter();
                writer.write(new ObjectMapper().writeValueAsString(contentToSend));
                writer.flush();
            });
}

2. Verify XSRF Token Retrieval Workflow

AngularJS automatically sends the X-XSRF-TOKEN header, but it needs to first receive the XSRF-TOKEN cookie from Spring Security. If you’re sending a POST/PUT/DELETE request without first making a GET request (to trigger the cookie being set), the token won’t exist—leading to a CSRF validation failure and unauthorized status.

Test this by:

  • Opening your app in a browser, then navigating to DevTools > Application > Cookies
  • Making a simple GET request (e.g., to your homepage or a public endpoint)
  • Confirm the XSRF-TOKEN cookie appears
  • Send your target POST/PUT/DELETE request and check if the X-XSRF-TOKEN header is included (DevTools > Network > Headers)

3. Check Your Custom AlreadyConnectedFilter

Your custom filter runs before the UsernamePasswordAuthenticationFilter—make sure it isn’t:

  • Blocking or modifying the GET request that sets the XSRF-TOKEN cookie
  • Stripping the X-XSRF-TOKEN header from incoming requests
  • Overwriting or clearing critical CSRF-related cookies

Temporarily comment out this filter to see if the issue resolves—if it does, you’ll know the filter is interfering with CSRF processing.

4. Validate Logout DELETE Request CSRF Compliance

You’ve set your logout endpoint to use a DELETE request, which requires a valid CSRF token. Ensure that when AngularJS sends the DELETE /logout request, it includes the X-XSRF-TOKEN header with the correct value from the cookie.

In DevTools, check the Network tab for the logout request—if the header is missing, double-check your AngularJS $httpProvider settings to confirm xsrfCookieName and xsrfHeaderName exactly match Spring’s defaults (XSRF-TOKEN and X-XSRF-TOKEN).

5. Cross-Origin (CORS) Check (If Applicable)

If your frontend is hosted on a different domain than your Spring Boot backend, you need to configure CORS to allow:

  • Credentials (cookies) to be sent across origins
  • The X-XSRF-TOKEN header to be included in requests

Add this CORS configuration bean to your Spring app if this applies:

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOriginPattern("*"); // Restrict this to your frontend domain in production
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:56:37