我的服务中定义了以下获取请求:
createAuthorizationHeader(user, pass) {
let headers: HttpHeaders = new HttpHeaders;
headers = headers.append('Accept', 'application/json, text/plain, */*');
headers = headers.append('Authorization', 'Basic ' + btoa(user + ':' + pass));
headers = headers.append('Content-Type', 'application/json; charset=utf-8');
console.log(headers);
return this.http.get(this._loginUrl, {
headers: headers
});
}
结果是:
OPTIONS https://localhost:8443/delivery/all 401 ()
Failed to load https://localhost:8443/delivery/all: Response for preflight does not have HTTP ok status.
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}
我也使用 Postman 发出了相同的 post 请求,但一切正常,因此本地服务器可以正常工作。
我不知道我的请求做错了什么。
CORS 合约要求飞行前的 OPTIONS 请求不需要进行身份验证。看起来您的后端需要对 OPTIONS 请求和 GET 进行身份验证。
当您使用 Postman 访问后端时,您仅发送 GET。 浏览器将首先发送一个 OPTIONS 请求(没有您的身份验证标头),并查找响应是否具有与发出请求的页面的来源相匹配的“Access-Control-Allow-Origin”标头。
如果对 OPTIONS 请求的响应不是 2xx,或者标头不存在,或者标头值与请求页面的来源不匹配,您将收到所遇到的错误,并且不会发出 GET 请求.
TLDR;将您的后端更改为在处理登录网址时不需要对 OPTIONS 方法进行身份验证。
如果是 .Net Web API 项目,请编辑 web.config 并删除下面的标签。
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
默认情况下,浏览器不允许用户进行跨域请求。
从 Angular 来看,为了避免这个错误,我们可以使用代理配置。
假设 Angular ui 正在 localhost:4200 上工作,并且它想要调用其余端点 url,例如: https://localhost:8443/delivery/all
以下步骤将解决此问题。
在 Angular 应用程序根文件夹中创建 proxy.config.json 文件。 (package.json 文件存在的地方) 代理的作用是简单地在前端应用程序运行的同一域+端口处获取浏览器请求,然后将该请求转发到后端 API 服务器。 CORS 是一个浏览器安全问题,不适用于进行“后端到后端”通信(如中间有代理的情况)。
内容应如下所示。
样品:
{
"/delivery/all/*": {
"target": "https://localhost:8443",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
}
我们的应用程序内向 /delivery/all/... 发出的所有请求都将转发到 https://localhost:8443/delivery/all/
注意:changeOrigin 属性。当您在后端使用某些虚拟代理(例如配置了 Apache2)时,您肯定必须将其设置为 true
在运行应用程序时添加代理配置。 Angular 支持“--proxy-config”,您可以在其中提供代理配置文件。 如果您使用“npm start”选项进行测试,则必须添加“--proxy-config”选项,如下所示。必须将其添加到 package.json 文件中。
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.config.json",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
如果您直接使用“ngserve”运行,那么它已按如下所示进行修改。 “ng服务--proxy-config proxy.config.json”
我们的 Angular 应用程序中的 HTTP 调用可以更改为这样。服务器会自动将请求转发到“https://localhost:8443/delivery/all”。
this.http.get('https://localhost:8443/delivery/all') .map(res => res.json());
到
this.http.get('/delivery/all') .map(res => res.json());
这里是更多信息的链接:https://sudhasoftjava.wordpress.com/2018/10/05/proxy-configuration-in-angular/
我们所做的是为 Cors 添加自定义配置。然后通过java服务器中的安全配置来启用它。如答案中所述,此服务器仅针对直接 REST 调用启用。
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
.allowedHeaders("*");
}
};
}
}
这涉及网络安全配置:
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/**")
.authorizeRequests().and()
.httpBasic()
.and()
.authorizeRequests().anyRequest().authenticated().and().cors();
}
在 POST 请求发送 OPTIONS 请求之前反应应用程序以检查您的 API。
您需要添加
nginx.conf
这个块。
location /api/ {
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://localhost:8080;
}
将此行添加到服务器标头配置的末尾
status_header(200);
应该可以解决问题
库里好像有bug,我发了204(也可以,但只有200才算可以)