如何在 Spring Boot 安全性中禁用 CORS

Posted

技术标签:

【中文标题】如何在 Spring Boot 安全性中禁用 CORS【英文标题】:How to disable CORS in sprint boot security 【发布时间】:2020-02-02 05:16:43 【问题描述】:

我想在 Spring Boot 安全性中完全禁用 CORS,但我尝试过的所有方法似乎都不起作用

我尝试添加自定义过滤器并将其作为 bean 注入,我还尝试在 WebSecurityConfigurerAdapter 中禁用 cors 我还尝试在配置 HttpSecurity 方法中添加过滤器。

这些链接我已经试过了:

1:CORS problems with spring boot security。

2:Spring security CORS Filter

我当前的代码状态如下:


@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 


    private final CustomUserDetailsService customUserDetailsService;
    private final AuthConfigProperties authConfigProperties;

    public WebSecurityConfig(@Lazy CustomUserDetailsService customUserDetailsService, AuthConfigProperties authConfigProperties) 
        this.customUserDetailsService = customUserDetailsService;
        this.authConfigProperties = authConfigProperties;
    

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception 
        return super.authenticationManager();
    

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder(authConfigProperties.getBcryptRounds());
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http
                .requestMatchers()
                .antMatchers("/login", "/logout", "/oauth/authorize")
                .and()
                .logout()
                .deleteCookies("JSESSIONID")
                .permitAll()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();

        http.cors().disable();

    


    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    



当我尝试访问前端的身份验证服务器时,我收到以下错误消息:

CORS 策略已阻止从源“http://localhost:3000”获取“http://localhost:8089/oauth/token”的访问权限:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。

【问题讨论】:

CORS 是浏览器端的东西;您确实需要启用吗?可能会帮助您阅读 about CORS 以了解它是什么。 @BoristheSpider 嗯,我不是在质疑你的回答,但如果是浏览器,为什么我们允许在后端配置它?在这两种情况下都有办法禁用它!我正在尝试将我的系统投入生产,但此问题不断出现。 不,没有办法禁用它。浏览器将所有运行的 JS 限制为单一来源策略 (SOP)。 CORS 允许您在服务器同意的情况下覆盖 SOP - 这就是它在服务器端的原因。您的身份验证服务器需要响应来自浏览器的预检提示“是的,我信任该来源,继续”。 @BoristheSpider 我已经通过设置代理解决了这个问题,为了使响应到达客户端,浏览器检查 Allow-Control-access-origin 的值是否相等到请求的原点。这就是我到现在为止的理解。如果我的评论没有任何意义,请纠正我。谢谢。 【参考方案1】:

此代码确实有效:


import com.example.myAuthServer.service.CustomUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 


    private final CustomUserDetailsService customUserDetailsService;
    private final AuthConfigProperties authConfigProperties;

    public WebSecurityConfig(@Lazy CustomUserDetailsService customUserDetailsService, AuthConfigProperties authConfigProperties) 
        this.customUserDetailsService = customUserDetailsService;
        this.authConfigProperties = authConfigProperties;
    

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception 
        return super.authenticationManager();
    

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder(authConfigProperties.getBcryptRounds());
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http
                .cors()
                .and()
                .requestMatchers()
                .antMatchers("/login", "/logout", "/oauth/authorize")
                .and()
                .logout()
                .deleteCookies("JSESSIONID")
                .permitAll()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();


    


    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    


但为了使原始帖子中显示的错误变为红色,您只需让浏览器知道请求的服务器 url 具有相同的“Allow-Control-Access-Origin”响应的 url。

我们可以通过在客户端应用代理来做到这一点,在我的例子中,我使用的是 react。

在 src 目录下添加一个名为 setupProxy.js 的文件。

然后编写如下代码:

const proxy = require("http-proxy-middleware");


module.exports = function (app) 
    app.use(proxy("/oauth/token", target: "http://localhost:8089")); // put your host and api
;

并像这样使用它:

fetch("/oauth/token", 
            method: "POST",
            body: qs.stringify(Auth.bodyForNewToken(username, password)),
            headers: 
                "Content-Type": "application/x-www-form-urlencoded",
                Authorization: "Basic " + btoa("<CLIENT>:<SECRET>")
            
        );

此代码只是一个提示,您需要更改必要的行!!!。

【讨论】:

【参考方案2】:

处理它的一种方法是添加 WebMvcConfigurer。尽管使用它,您应该考虑环境 profile(dev、prod 等),并且您可以将 WebSecurityConfigurerAdapter 保留为 cors 配置默认值。 (不需要禁用它)

一个例子:

@Configuration
public class WebMvc implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*");
    

【讨论】:

我认为它和这篇文章***.com/a/58227186/10420300 一样,但是以一种通用的方式,这似乎也是一个糟糕的主意。 否,因为这是一个通用代理,您不需要控制 N 个控制器,它将应用于所有路由,如果您输入 @Profile("dev") 则不会有什么问题。当然,您可以在参数中更具体,但总体而言它会起作用

以上是关于如何在 Spring Boot 安全性中禁用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 安全性中禁用 CORS

如何在 Spring Boot 2.2.0 的集成测试中禁用安全性?

如何在 Spring Boot 应用程序中禁用/忽略 @PreAuthorize

Spring Boot 1.5 禁用 oauth2 安全性

无法在 Spring Boot 中禁用安全性 [重复]

Spring Boot 在本地环境中禁用 SAML 安全性