Spring Boot+AngularJS 1.6集成CSRF保护遇未授权问题求助
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
authenticationEntryPointearly in the chain, then later redefinehttp.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-TOKENcookie appears - Send your target POST/PUT/DELETE request and check if the
X-XSRF-TOKENheader 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-TOKENcookie - Stripping the
X-XSRF-TOKENheader 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-TOKENheader 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

