我有一个关于在与 Angular 框架和 Spring security 6 集成时如何将 JWT 令牌与 CSRF 保护结合起来的问题。虽然有很多关于是否同时使用 CSRF 和 JWT 的帖子,但目的是寻求有关如何实现和实现的建议了解预期行为。我一直在这里关注 SPRING DOCS - https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration-javascript
对此最常见的答案是禁用 csrf,因为它是无状态的,但在某种程度上状态是由前端 UI 维护的。
我的应用程序遇到以下行为,我不知道如何解决它。
不断刷新csrf cookie的正确方法是什么?
以下是我的项目配置
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
CsrfTokenRequestAttributeHandler crsfTokenRequestHandler = new CsrfTokenRequestAttributeHandler();
http
//.securityContext(contextConfig -> contextConfig.requireExplicitSave(false)) // removed and only used for JSESSIONID
.sessionManagement(sessionConfig-> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.cors(corsConfig -> corsConfig.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration myconfig = new CorsConfiguration();
myconfig.setAllowedOrigins(Collections.singletonList("http://localhost:4200"));
myconfig.setAllowedMethods(Collections.singletonList("*"));
myconfig.setAllowCredentials(true);
myconfig.setAllowedHeaders(Collections.singletonList("*"));
myconfig.setExposedHeaders(Arrays.asList("Authorization"));
myconfig.setMaxAge(3600L);
return myconfig;
}
}))
//.csrf(csrf -> csrf.disable())
.csrf(csrfConfig ->
csrfConfig.csrfTokenRequestHandler(crsfTokenRequestHandler)
.ignoringRequestMatchers(REGISTER_URL, H2_CONSOLE_URL)
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
.addFilterAfter(new JWTTokenGeneratorFilter(), BasicAuthenticationFilter.class)
.addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class)
.addFilterBefore(new JWTTokenValidationFilter(), BasicAuthenticationFilter.class)
.requiresChannel(rcc -> rcc.anyRequest().requiresInsecure())
.authorizeHttpRequests((requests) -> requests
.requestMatchers(H2_CONSOLE_URL).permitAll()
.requestMatchers(REGISTER_URL, "/error", "/invalidSession").permitAll()
.requestMatchers(LOGIN_URL,OCCASSIONS_LIST_URL, OCCASSION_GET, OCCASSIONS_EDIT, OCCASIONS_ADD, USER_GET, USER_EDIT).authenticated())
.headers(h -> h.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin));
//http.formLogin(flc -> flc.disable()); // this is a login page with a user name and password using Spring MVC
http.formLogin(withDefaults());
http.httpBasic(hbc -> hbc.authenticationEntryPoint(new CustomBasicAuthenticationEntryPoint())); // this is header based
http.exceptionHandling(ehc -> ehc.accessDeniedHandler(new CustomAccessDeniedHandler()));
return http.build();
}
您链接到的 CSRF 章节提供了有关“禁用 CSRF”的建议,而该建议又链接到“何时使用 CSRF 保护”的说明。该解释旨在帮助您理解为什么您不应该在基于浏览器的应用程序中禁用 CSRF。 在配置 CSRF 应用程序方面,您链接的页面包含您需要的所有建议,您只需密切关注即可。但是,添加您自己的自定义 JWT 过滤器是不可取的,如果实施不正确,可能会导致类似您所看到的问题。请参阅 OAuth2 资源服务器概述,其中包含解释如何
使用自定义 JWT(如果您必须使用)的部分。您不需要实现自己的 JWT 支持。 注意:您可以使用 Spring Authorization Server
轻松构建基于 OAuth2 的解决方案,这比支持自定义 JWT 更有利于学习。您的后端服务(API)将继续像大多数人所认为的那样“无状态”。无论如何,当您启用 Spring Security 的 OAuth2 资源服务器附带的 JWT 支持时,您应该继续遵循 CSRF 章节
中的建议,并启用 CSRF 保护。有多种选项可以将您的前端与 CSRF 正确集成。