CSRF 和 JWT 与 Sping Security 6 无状态 REST

问题描述 投票:0回答:1

我有一个关于在与 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 维护的。

我的应用程序遇到以下行为,我不知道如何解决它。

  1. 成功登录后,会在 浏览器
  2. 任何操作(GET、PUT、POST、DELETE)后,cookie 未设置
  3. 由于cookie被取消设置,我无法再执行任何不安全的操作 诸如 POST、PUT 或 DELETE 之类的操作,直到设置新的 cookie 执行 GET(被认为是安全操作)。

不断刷新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();
    }
authentication cookies spring-security jwt csrf
1个回答
0
投票

您链接到的 CSRF 章节提供了有关“禁用 CSRF”的建议,而该建议又链接到“何时使用 CSRF 保护”的说明。该解释旨在帮助您理解为什么您不应该在基于浏览器的应用程序中禁用 CSRF。 在配置 CSRF 应用程序方面,您链接的页面包含您需要的所有建议,您只需密切关注即可。但是,添加您自己的自定义 JWT 过滤器是不可取的,如果实施不正确,可能会导致类似您所看到的问题。请参阅 OAuth2 资源服务器概述,其中包含解释如何

使用自定义 JWT

(如果您必须使用)的部分。您不需要实现自己的 JWT 支持。 注意:您可以使用 Spring Authorization Server

轻松构建基于 OAuth2 的解决方案,这比支持自定义 JWT 更有利于学习。您的后端服务(API)将继续像大多数人所认为的那样“无状态”。

无论如何,当您启用 Spring Security 的 OAuth2 资源服务器附带的 JWT 支持时,您应该继续遵循 CSRF 章节

中的建议,并启用 CSRF 保护。有多种选项可以将您的前端与 CSRF 正确集成。

© www.soinside.com 2019 - 2024. All rights reserved.