在Angular 2

时间:2016-12-30 23:54:55

标签: javascript angular typescript cors angular2-http

我意识到我的头衔有点模糊,但这是我的情况。我刚刚启动了一个应用程序,我正在实现JWT进行身份验证。我已经设置了服务器端,并且可以验证它是否按预期工作。

奇怪的是,当您点击按钮登录时,在Chrome和Firefox中,它会发送一次请求,而不会发送请求正文。在Edge中,它按照Chrome的方式提交两次,然后在身体完好后立即第二次提交。

我现在已经将登录硬编码直接写入帖子请求中,尝试尽可能多地删除。

header.component.html

<ul id="links">
    <li>
        <a href="/">Home</a>
    </li>
    <li>
        <a href="/census">Census</a>
    </li>
    <li>
        <button (click)="login()">Login</button>
    </li>
</ul>

header.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { AuthenticationService } from '../_services/Authentication.Service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  constructor(private _auth: AuthenticationService, private router: Router) { }

  ngOnInit() {
  }

  login() {
        this.loading = true;
        this._auth.login(this.model.username, this.model.password)
            .subscribe(result => {

            });
    }

}

Authentication.Service.ts

import { Injectable } from '@angular/core';
import { Http, Headers, Response, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'
 
@Injectable()
export class AuthenticationService {
    public token: string;
 
    constructor(private http: Http) {
        // set token if saved in local storage
        var currentUser = JSON.parse(localStorage.getItem('currentUser'));
        this.token = currentUser && currentUser.token;
    }
 
    login(usn: string, psw: string): Observable<boolean> {
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        return this.http.post('http://localhost:5000/auth', JSON.stringify({ username: "email-removed", password: "password-removed" }), options)
                    .map((response: Response) => { return true; });
    }
}

以下是我从Chrome看到的第一个请求的请求,响应为空

Request URL:http://localhost:5000/auth
Request Method:OPTIONS
Status Code:200 OK
Remote Address:127.0.0.1:8888
Response Headers
view source
Allow:POST, OPTIONS
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Sat, 31 Dec 2016 00:08:05 GMT
Server:Werkzeug/0.11.13 Python/3.5.2
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8,es;q=0.6
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Host:localhost:5000
Origin:http://localhost:4200
Proxy-Connection:keep-alive
Referer:http://localhost:4200/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

这是fiddler捕获的第二个请求。当我点击chrome中的按钮

时,它永远不会发生
POST http://localhost:5000/auth HTTP/1.1
Accept: */*
content-type: application/json
Referer: http://localhost:4200/
Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.7,zh-Hans;q=0.5,es-US;q=0.3,es;q=0.2
Origin: http://localhost:4200
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393
Content-Length: 58
Host: localhost:5000
Connection: Keep-Alive
Pragma: no-cache

{"username":"removed","password":"removed"}

第二次的反应

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0ODMxNDE5NDIsImlkZW50aXR5IjoiNTg2NmJiNDkwYzE3ZDdlMzk4MTk5MWNhIiwiZXhwIjoxNDgzMTQyMjQyLCJuYmYiOjE0ODMxNDE5NDJ9.VZGBYnPKPwyR0lWdG3kR8AecbLNlYCHMC1nimAHeP3w"
}

这是你的另一个奇怪/线索。后端是Python / Flask休息。当我看到请求进来时,这就是我所看到的。说OPTIONS的是空请求,那些说POST的第二个只发生在Edge中并且是正确的。 enter image description here

3 个答案:

答案 0 :(得分:1)

您似乎遇到了来自原始请求的问题 页面主机(localhost:5000)与目标(POST)不同。

当发生这种情况时,Chrome会发出preflighted request

  

与简单请求(如上所述)不同,&#34;预先发布&#34;首先要求   通过OPTIONS方法向该资源发送HTTP请求   其他域,以确定实际请求是否安全   发送。跨站请求是这样的预检,因为它们可能   对用户数据有影响。

您从服务器获得的响应并未包含所需的CORS headers,因此Chrome不会发出实际的#include "backward.hpp" void stacker() { using namespace backward; StackTrace st; st.load_here(99); //Limit the number of trace depth to 99 st.skip_n_firsts(3);//This will skip some backward internal function from the trace Printer p; p.snippet = true; p.object = true; p.color = true; p.address = true; p.print(st, stderr); } 请求。

答案 1 :(得分:1)

如上所述,Chrome会发出预检请求。 要绕过它,您可以安装this Chrome extension以启用CORS并将*'Allow-Control-Allow-Origin:'添加到标头中。这对我来说对我来说是本地主机上的django:8000和本地主机上的angular2:4200。

答案 2 :(得分:0)

确保您正在呼叫的路由末尾有一个尾部斜杠。所以不要打电话

'http://localhost:5000/auth'

你的目标

'http://localhost:5000/auth/'

希望这有帮助。