如何在Spring Boot + Spring Security应用程序中配置CORS? [英] How to configure CORS in a Spring Boot + Spring Security application?

查看:5724
本文介绍了如何在Spring Boot + Spring Security应用程序中配置CORS?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Spring Boot与Spring Security和Cors支持。

I use Spring Boot with Spring Security and Cors Support.

如果我执行以下代码

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:a'
do xmlhttp.send

我得到结果

200

如果我使用错误的凭证测试,例如

If I test with wrong credentials like

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:aa'
do xmlhttp.send

而不是401(这是春天安全中错误认证的标准代码)我得到

instead of getting 401 (that is the standard code for wrong authentication in spring security) I get

0

以下浏览器通知:

GET http:// localhost:5000 / api / token

XMLHttpRequest无法加载 http:// localhost:5000 。在所请求的资源上没有Access-Control-Allow-Origin头。原因 http:// localhost:3000 因此不允许访问。该响应的HTTP状态码为401.

XMLHttpRequest cannot load http://localhost:5000. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 401.

我正在开发前端代码,需要从服务器响应中获取有用的http状态代码来处理这种情况。我需要一些比0更有用的。还有响应体是空的。我不知道我的配置是否错误,或者它是一个软件错误,我也不知道在哪里,如果它是铬(使用arch linux)或弹簧安全。

I'm developing front-end code that needs useful http status codes from server responses to handle the situation. I need something more useful than 0. Also the response body is empty. I dont know if my config is wrong, or it's a software bug and I also don't know where, if it's chromium (using arch linux) or spring security.

我的Spring配置是:

My Spring Config is:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
@RequestMapping("api")
public class Controller {
    @RequestMapping("token")
    @CrossOrigin
    Map<String, String> token(HttpSession session) {
        return Collections.singletonMap("token", session.getId());
    }
}

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}



如果我用curl测试一切都很完美,因为没有CORS支持,但我试图模拟CORS与OPTION请求,结果也确定。

If I test with curl everything works perfect, I think because no CORS support needed, but I tried to simulate the CORS with OPTION requests and the result was also ok.

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTpha"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTpha
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin,Accept,X-Requested-    With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
< x-auth-token: 58e4cca9-7719-46c8-9180-2fc16aec8dff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:15:44 GMT
< 
* Connection #0 to host localhost left intact
{"token":"58e4cca9-7719-46c8-9180-2fc16aec8dff"}

且凭据错误:

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTp"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTp
> 
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< WWW-Authenticate: Basic realm="Realm"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:16:15 GMT
< 
* Connection #0 to host localhost left intact
{"timestamp":1462119375041,"status":401,"error":"Unauthorized","message":"Failed to decode basic authentication token","path":"/api/token"}

编辑:
为了避免误解。我使用1.3.3 Spring Boot。
博客帖子写道:

To avoid misunderstandings. I use 1.3.3 Spring Boot. The Blog post writes:


CORS支持将在即将到来的Spring Boot 1.3版本中提供, 1.3.0.BUILD-SNAPSHOT构建。

CORS support will be available in the upcoming Spring Boot 1.3 release, and is already available in the 1.3.0.BUILD-SNAPSHOT builds.

使用控制器方法在Spring Boot应用程序中使用@CrossOrigin注释的CORS配置不需要任何特定配置。

Using controller method CORS configuration with @CrossOrigin annotations in your Spring Boot application does not require any specific configuration.

可以通过使用定制的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置:

Global CORS configuration can be defined by registering a WebMvcConfigurer bean with a customized addCorsMappings(CorsRegistry) method:

我添加了以下代码以启用全局cors支持。实际上我已经尝试过,但它的结果是一样的。我最近再次尝试,结果是一样的。

I have added following code to enable global cors support. actually I have tried this before but it the result was the same. I tried it again recently and the result is the same.

@Configuration
public class MyConfiguration {

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

这个想法,问题来自授权过程是一个有趣的。如何更改重定向到任何资源以避免此冲突?

The idea, that the problem comes from a redirect between the authorization process is an interesting though. how can i change the redirect to any resources to avoid this conflict?

编辑:

更接近解决方案。我通过添加
Access-Control-Allow-Origin:*
到所有请求,测试我的nodejs服务器支持cors没有问题。

I guess I am closer to a solution. I have tested with my nodejs server that supports cors without problems by adding Access-Control-Allow-Origin: * to all requests.

像Stefan Isele已经提到,似乎spring安全重定向或不添加CORS头,这就是为什么请求似乎被打破。因此,虽然春天安全检查身份验证,它必须添加正确的标题。

Like Stefan Isele has already mentioned it seems that spring security redirects or doesn't add the CORS header so that's why the request seems to be broken. So while spring security is checking the authentification it has to add the proper header.

有人知道如何这样做吗?

Does anyone know how to do so?

编辑:

我发现了一个解决方法,似乎是丑陋。我已经为spring boot启动了一个github问题,其中我描述了解决方法: https://github.com/spring -projects / spring-boot / issues / 5834

I found a workaround, that seems to be ugly. I have started a github issue for spring boot where I describe the workaround: https://github.com/spring-projects/spring-boot/issues/5834

推荐答案

由于Spring Security是基于过滤器的安全框架,目前没有办法知道在请求处理链中的Spring MVC级别发生的CORS配置和处理,因此例如预检CORS请求被阻止。

Since Spring Security is a filter based security framework, it has currently no way to be aware of CORS configuration and processing that happens at Spring MVC level later in the request processing chain, so for example preflight CORS requests are blocked.

你可以配置Spring Security以通过指定 .requestMatchers(CorsUtils :: isPreFlightRequest).permitAll()来允许 WebSecurityConfigurerAdapter#configure(HttpSecurity) code>但这种方法有两个缺点:

You can configure Spring Security to allow preflight requests in WebSecurityConfigurerAdapter#configure(HttpSecurity) by specifying .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() but this approach has 2 drawbacks:


  • Spring Security本身处理的请求CORS响应标头,并且将被浏览器阻止,但不允许您获取错误状态代码

  • 通过允许 OPTIONS 有CORS标头的请求

  • Requests handled by Spring Security itself (like not authorized response) won't contain CORS response headers and will be blocked by the browser without allowing you to get the error status code for example
  • That increases the attack surface of your application by allowing OPTIONS requests that have CORS headers

我刚刚更新了我的Spring + CORS博客文章与当前推荐的方法,这是使用< a href =http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/filter/CorsFilter.html> CorsFilter 我们提供Spring Framework 4.2+。这个过滤器必须在Spring Security之前,所以在Spring Boot应用程序的情况下你可以声明如下:

I have just updated my Spring + CORS blog post with the current recommended approach, which is to use the CorsFilter we provide with Spring Framework 4.2+. This filter must be before Spring Security one, so in the case of a Spring Boot application you can declare it as following:

@Configuration
public class MyConfiguration {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://domain1.com");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

我们还在努力实现更好的集成Spring Security了解Spring MVC级别的CORS配置,以便在使用Spring MVC + Spring Security时实现CORS的无缝支持。如果我们设法支持,我将更新响应。

We are also working on a better integration that could allow Spring Security to know Spring MVC level CORS configuration in order to achieve seamless CORS support when using Spring MVC + Spring Security. I will update the response if we manage to support that.

这篇关于如何在Spring Boot + Spring Security应用程序中配置CORS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆