在 Spring Boot 和角形护套之间搬运CORS和CSRF

svgewumm  于 2022-12-23  发布在  Spring
关注(0)|答案(4)|浏览(126)

我有一个运行在端口8888上的 Boot 后端应用程序和一个运行在4200上的Angular前端应用程序。
在我的Sping Boot 应用程序中,我定义了以下bean来处理CORS:

@Bean
public WebMvcConfigurer webMvcConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    };
}

我的HttpSecurity配置如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().disable()
        // ... the rest of the config
}

有了这个配置,一切正常,我可以成功地从Angular应用程序调用我的API。
但我想启用CSRF,因此我将安全配置更改为以下内容:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        // ... the rest of the config
}

我已经添加了以下HttpInterceptor到我的Angular 应用程序:

constructor(private tokenExtractor: HttpXsrfTokenExtractor) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.tokenExtractor.getToken();
    if (token) {
        req = req.clone({ setHeaders: { 'X-XSRF-TOKEN': token } });
    }
    return next.handle(req);
}

问题是tokenExtractor.getToken()总是返回null
相应的请求和响应标头如下所示:

XSRF-TOKEN响应cookie存在。
我想不出是什么问题。
我试过在我的Angular应用程序中导入HttpClientXsrfModule,但没有任何区别。
我真的很感激任何建议。

l7wslrjt

l7wslrjt1#

不需要。你可以使用chrome nosecurity或者安装允许控制允许来源插件来解决这个问题。

093gszye

093gszye2#

我在我的Sping Boot 应用程序中使用了这段代码,它与Angular配合得很好
@Component 公共类SimpleCORSFilter实现Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

希望有帮助:)

gmxoilav

gmxoilav3#

正如文档中所说[...您可以从单个控制器或全局启用跨源资源共享(CORS)...]

  • 控制器方法CORS配置:可使用@CrossOrigin注记启用
  • 全球CORS配置:
@Configuration
public class CorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer(){
        return new WebMvcConfigurer(){
            @Override
            public void addCorsMappings(CorsRegistry registry){

                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*").maxAge(3600);

            }
        };
    }
}
tjjdgumg

tjjdgumg4#

实际上Spring在这里处理服务器端的实现,你所要做的就是添加.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())配置,就像你之前做的那样。
Spring在这里为您实现的安全模式是“cookie-to-header”模式。Spring在GET请求的响应中添加了一个名为XSRF-TOKEN的cookie。假设值为aa5f7a64-cf4d-4706-b5aa-bcdec2b41798
当你尝试做一个POST请求时,Spring将返回一个403 Forbidden,除非你添加一个带有键X-XSRF-TOKEN和你从GET请求中得到的cookie值的头,对于我们的例子,这将是aa5f7a64-cf4d-4706-b5aa-bcdec2b41798
Spring会检查cookie的值和header的值是否相同,只有当它们相同时,请求才会通过,否则会得到一个403 Forbidden

相关问题