为什么 Spring 安全性身份验证会导致 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;
    }
}

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);
    }
}

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

无论是从我的pom.xml中删除 Spring 安全性还是添加此配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/resource").permitAll();
    }
}

解决了问题。

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

根据 Spring 引导文档:

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

跨域资源共享 (CORS) 是 W3C 规范 由大多数浏览器实现,允许您指定哪种 跨域请求已获得授权,而不是使用安全性较低的请求 以及基于 IFRAME 或 JSONP 的强大解决方法。

收到此错误是因为需要在安全配置中添加筛选器。在配置中,添加:

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

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

@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;
}

这对我来说很好用。

想知道的是为什么我收到 CORS 错误而不是 401 访问需要用户的地址时未经授权 认证。

您收到此错误是因为在您的实际请求(POST,GET...)之前,浏览器会执行预检请求(OPTIONS)以验证被调用的服务器是否能够处理CORS请求。

在此请求期间,将验证Access-Control-Request-MethodAccess-Control-Request-Header,并将一些其他信息添加到标头中。

然后,您会收到 CORS 错误,因为如果 ITEMS 验证在 OPTIONS 请求上失败您的实际请求甚至没有完成

您可以在此处查看 CORS 验证如何工作的流程图

有趣的是,只有在预检请求期间,当服务器无权应答 OPTIONS 请求时,您只会在预检请求期间获得 HTTP 错误状态,例如 401。

最新更新