我尝试使用Angular的HttpClient发送带有授权标头的请求,但标头未成功设置。
这是我的代码。
import {HttpClient, HttpHeaders} from '@angular/common/http';
constructor(private http: HttpClient,
private auth: AuthService) {
}
sendRequest() {
this.http.get(this.url, {
headers: new HttpHeaders().set('Authorization', 'Bearer ' + this.auth.getAccessToken())
}).subscribe(
data => {
console.log(data);
},
error => {
console.log(error);
}
);
}
这里是网络调试头源。
OPTIONS /userinfo HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
Referer: http://localhost:4200/user
Accept-Encoding: gzip, deflate, br
Accept-Language: ja,en-US;q=0.8,en;q=0.6
响应标题如下。
HTTP/1.1 400 Bad Request
Access-Control-Allow-Origin: *
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Sun, 27 Aug 2017 23:45:15 GMT
Content-Length: 18
有什么不对吗?
答案 0 :(得分:13)
如果查看问题中包含的标题,您会看到这是一个OPTIONS请求。这表明您正在尝试发出跨站点请求,并且浏览器的CORS(跨源资源共享)协议已启动。
您显然发出了一个GET请求,其中包含一个域(或端口号)的凭据,该域与发出请求的页面的来源不同。事实上,我们从您的标题中看到源是端口4200(角度开发服务器的标准端口),并且请求是对端口8080(可能是java后端?)。
标准CORS协议是供浏览器进行预检"检查,通过发送OPTIONS请求来查看是否有一个Access-Control-Allow-Origin标头返回,说明允许来源访问目的地。
如果标题返回正常,则浏览器将发出GET请求。如果没有,您将收到401响应。
所有这些都是由浏览器完成的,并且无法控制。
规范(https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0)表示当浏览器将OPTIONS请求作为预检的一部分发送时,它不得包含您的授权标头 - 只会在GET上发送。
所以,不 - 这里没有任何问题 - 它按预期工作。
现在,如果在此之后,您获得401并且从未发送GET,那么您必须修改服务器以发送适当的Access-Control-Allow-Origin标头以响应OPTIONS请求。
有关CORS的更多信息,请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS