Angular JWT Auth - 总是401未授权

时间:2017-10-27 09:04:50

标签: php angular cakephp jwt

我正在创建一个简单的cakephp后端。对于我使用角度的前端。 Angular通过api路由(使用ADmad JWT插件)连接到后端,并且应该登录以获取令牌。

我的Api/UsersController.php

public function token()
{
    $user = $this->Auth->identify();
    if (!$user) {
        throw new UnauthorizedException('Invalid username or password');
    }
    $this->set([
        'success' => true,
        'data' => [
            'token' => JWT::encode(
                [
                    'sub' => $user['id'],
                    'exp' =>  time() + 604800
                ],
                Security::salt()
            )
        ],
        '_serialize' => ['success', 'data']
    ]);
}

现在,当我想测试与Postman的连接时,(以下选项)可以正常工作:

Request-Type: POST
URL:          http://cake3api.app/api/users/token.json
Headers:      Accept       => application/vnd.api+json
              Content-Type => application/vnd.api+json
Body (JSON array):
{
    "username":"test",
    "password":"1234"
}

答案:

 {
     "success": true,
     "data": {
         "token": "HERE_COMES_THE_TOKEN_AS_ANSWER"
      }
 }

现在我想在Angular4中使用这个auth-api。我创建了一个AuthService,所以我可以对蛋糕api做出承诺:

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class AuthService {

    private BASE_URL: string = 'http://cake3api.app/api/users';
    private headers: Headers = new Headers({
        'Content-Type' : 'application/vnd.api+json',
        'Accept' : 'application/vnd.api+json'
    });

    constructor(private http: Http) { }

    login(user): Promise<any> {
        let url: string = `${this.BASE_URL}/token.json`;
        return this.http.post(url, user, {headers: this.headers}).toPromise();
    }
}

我正在LoginComponent

中调用该服务
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})

export class LoginComponent implements OnInit {

    constructor(private auth: AuthService) { }

    ngOnInit(): void {
        let sampleUser: any = {
            username: 'test' as string,
            password: '1234' as string
        };

        this.auth.login(sampleUser).then((user) => {
            console.log(user.json());
        }).catch((err) => {
            console.log(err);
        });
    }

}

有了这个,我收到以下信息:

OPTIONS http://cake3api.app/api/users/token.json 401 (Unauthorized)
  

无法加载http://cake3api.app/api/users/token.json:响应   预检具有无效的HTTP状态代码401

// XHR Request & Response (from console)
**GENERAL**
Request URL:http://cake3api.app/api/users/token.json
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:127.0.0.1:80
Referrer Policy:no-referrer-when-downgrade

**RESPONSE HEADERS**
Access-Control-Allow-Headers:origin, x-requested-with, content-type
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Connection:Keep-Alive
Content-Length:247
Content-Type:application/json; charset=UTF-8
Date:Fri, 27 Oct 2017 08:56:17 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.27 (Win32) OpenSSL/1.0.2l PHP/7.1.9
X-DEBUGKIT-ID:ac7b0f38-4c97-44d4-8c26-9f95b94ce937
X-Powered-By:PHP/7.1.9

**REQUEST HEADERS**
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,bs;q=0.2
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:cake3api.app
Origin:http://localhost:4200
Pragma:no-cache
Referer:http://localhost:4200/login
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

任何人都知道,为什么这个星座不起作用?我的想法是,angular不会发送请求(发送错误的标题?)。奇怪的是,我和邮递员的测试工作有效,但没有角度。

如果有人认为这是因为蛋糕不接受ORIGIN标题,那就应该。我在./.htaccess

中启用了访问控制功能
<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
    Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</IfModule>

修改

因为问题似乎是浏览器发送OPTIONS - 请求,我绕过了,但仍然没有工作。

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

错误消息消失了,但是出现了一个新消息:

  

无法加载http://cake3api.app/api/users/token.json:响应   预检请求未通过访问控制检查:否   请求中存在“Access-Control-Allow-Origin”标头   资源。因此不允许来源“http://localhost:4200”   访问。

现在它说没有设置标题Access-Control-Allow-Origin。但我已将其设置在我.htaccess - 请求解决方法的同一OPTIONS文件中。多么令人不安的问题,已经为这么小的事情浪费了很多时间......

2 个答案:

答案 0 :(得分:0)

  

无法加载http://cake3api.app/api/users/token.json:响应   预检具有无效的HTTP状态代码401

正如你所说邮递员能够通过浏览器从服务器收到正确的回复,你得到了上述例外,这已经解释了什么是潜在的问题。

预检请求是在您实际请求之前由浏览器发出的HTTP OPTION类型请求,该错误意味着您没有明确处理OPTION请求。

确保您的php服务器接受OPTION请求并且它应该正常工作

编辑: 尝试为标题Access-Control-Allow-Origin&#39;

添加主机而不是通配符*
Header set Access-Control-Allow-Origin "http://localhost:4200"

并检查chrome dev工具中的HTTP响应标头,确保您拥有正确的标题。

enter image description here

答案 1 :(得分:-1)

在配置方法中添加 httpsercurity.cors 以避免预检。