我正在尝试使用 Angular2 作为前端和 cakephp 3 作为 REST Api 创建一个应用程序,身份验证工作正常,但是当我尝试访问任何其他网址时,我收到 401 Unauthorized状态,我注意到请求方法是 OPTIONS 而不是我在代码中使用的 GET,并且带有我的 token 的 Authorization header 是未发送到服务器:
这是我的 user.service.ts 代码:
constructor(private http: Http,
private router: Router,
) { }
login(email: string, password: string){
let headers: Headers = new Headers({ 'Accept': 'application/json','Content-Type': 'application/json' });
let options: RequestOptions = new RequestOptions({headers: headers});
return this.http.post('http://www.students.com/api/users/token.json', {email: email, password: password}, options)
.map((data: Response)=> data.json())
.subscribe(
(data)=> this.handlData(data),
(error)=> this.handlError(error)
);
}
getSessionData(){
let token = localStorage.getItem('usr_token');
let headers = new Headers({ 'Accept': 'application/json', 'Authorization': 'Bearer ' + token });
let options: RequestOptions = new RequestOptions({headers: headers});
return this.http.get('http://www.students.com/api/users/getSessionData', options).subscribe(
data => console.log(data),
err => console.log(err)
);
}
handlData(data){
if(data.success){
let usrData = data.data.user;
this.user = new User(usrData.email, usrData.firstname, usrData.lastname, usrData.role, data.data.token);
localStorage.setItem('id_token', data.data.token);
}
}
handlError(error){
console.log(error);
}
我尝试使用 angular2-jwt 模块,但遇到了同样的错误,为了确保我的 API 正常工作,我使用 Postman chrome 扩展对其进行了测试,它按预期工作:
这是我的 Apache2 VirtualHost 配置
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/students
ServerName www.students.com
<Directory /var/www/html/students>
Require all granted
Options Indexes FollowSymLinks Includes
AllowOverride all
</Directory>
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
</VirtualHost>
有人遇到同样的问题吗?有什么想法为什么会发生这种情况吗?
最佳答案
这不是 Angular 的问题,而是后端的问题。 Angular 尝试通过检查服务器是否在 OPTIONS 请求上返回 OK 来发出预检请求。您应该将后端设置为针对 OPTIONS 请求响应 200 或 204。
如果您使用的是node.js:
app.use('/api', (req, res, next) => {
/** Browser check for pre-flight request to determine whether the server is webdav compatible */
if ('OPTIONS' == req.method) {
res.sendStatus(204);
}
else next();
});
或者 laravel (PHP):
App::before(function($request)
{
// Sent by the browser since request come in as cross-site AJAX
// The cross-site headers are sent via .htaccess
if ($request->getMethod() == "OPTIONS")
return new SuccessResponse();
});
这将告诉浏览器服务器可以适本地处理 webdav 请求方法。
更新:由 CakePHP 上的询问者添加:
public function initialize() {
parent::initialize();
if($this->request->is('options')) {
$this->response->statusCode(204);
$this->response->send();
die();
}
$this->Auth->allow(['add', 'token']);
}
关于Angular 2不使用JWT身份验证发送授权 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41074505/