我有一个用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-Method
和Access-Control-Request-Header
,并将一些其他信息添加到标头中。
然后,您会收到 CORS 错误,因为如果 ITEMS 验证在 OPTIONS 请求上失败,您的实际请求甚至没有完成。
您可以在此处查看 CORS 验证如何工作的流程图
有趣的是,只有在预检请求期间,当服务器无权应答 OPTIONS 请求时,您只会在预检请求期间获得 HTTP 错误状态,例如 401。