为什么 Spring Security 身份验证会导致 CORS 错误

Jea*_*ger 1 java spring spring-security cors

我有一个用 Java 制作的带有 Spring Boot、Security 和 Web 的后端服务器和一个用 Angular 制作的客户端。

目前我正在尝试在localhost:8080/resource.

该地址的控制器如下所示:

@RestController
public class IndexController {
    @CrossOrigin
    @RequestMapping("/resource")
    public Map<String, Object> home() {
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("id", UUID.randomUUID().toString());
        model.put("content", "Hello World");

        return model;
    }
}
Run Code Online (Sandbox Code Playgroud)

Angular 客户端(执行请求的部分)是这样的:

import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    styleUrls: ["./app.component.css"]
})
export class AppComponent {
    public title = "Security Client";
    public greeting = {};

    constructor(private http: HttpClient) {
        http.get("http://localhost:8080/resource").subscribe(data => this.greeting = data);
    }
}
Run Code Online (Sandbox Code Playgroud)

仅使用所示内容的问题是我收到 CORS 错误。

无论是从我的中删除 Spring Securitypom.xml还是添加此配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/resource").permitAll();
    }
}
Run Code Online (Sandbox Code Playgroud)

解决问题。

我想知道的是为什么我在访问需要用户身份验证的地址时收到 CORS 错误而不是 401 Unauthorized。

And*_*eco 5

根据spring boot文档:

出于安全原因,浏览器禁止对当前来源之外的资源进行 AJAX 调用。例如,您可以在一个选项卡中拥有您的银行帐户,而在另一个选项卡中拥有 evil.com。来自 evil.com 的脚本不应该能够使用您的凭据向您的银行 API 发出 AJAX 请求?—?例如从您的帐户中取款!

跨域资源共享 (CORS) 是大多数浏览器实现的 W3C 规范,它允许您指定授权的跨域请求类型,而不是使用基于 IFRAME 或 JSONP 的安全性较低且功能较弱的解决方法。

您收到此错误是因为您需要在安全配置中添加过滤器。在您的配置中,添加:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors()
    .and()
    .authorizeRequests().antMatchers("/resource").permitAll();
}
Run Code Online (Sandbox Code Playgroud)

在同一个文件中,您应该添加:

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", 
    "DELETE", "OPTIONS"));
    configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", 
    "x-auth-token"));
    configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
    UrlBasedCorsConfigurationSource source = new 
    UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);

    return source;
}
Run Code Online (Sandbox Code Playgroud)

这对我来说很好用。

  • CORS 验证发生在通过 OPTIONS 请求(通过飞行前请求的方式调用)发出 POST、GET... 请求之前。要更好地了解请求流,您可以查看 [this](https://www.html5rocks.com/en/tutorials/cors/) 和 [this](https://www.html5rocks.com/static/images/cors_server_flowchart .png) (3认同)