2016-12-30 60 views
3

我意识到我的标题有点模糊,但这是我的情况。我刚刚开始一个应用程序,在该应用程序中我正在实施JWT进行身份验证。我有我的服务器端设置,并可以验证它是否按预期工作。在Angular 2中提交发布请求时出现的奇怪行为

奇怪的是,当你点击按钮登录时,在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 

这是由提琴手捕获的第二个请求。当我点击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 /烧瓶休息。当我看到这些请求是我看到的。那些说OPTIONS是空的请求,那些说POST是仅在Edge中发生的第二个并且是正确的。 enter image description here

+0

你在答复中得到了什么?页面是否托管在相同的主机('http:// localhost:5000')?或者是另一个? (如果端口不同,则主机为) –

+0

没有主体的端口会返回空的200响应,包含登录名和密码的响应会返回我的JWT。 – Jhorra

+0

您是否可以在Chrome开发人员工具网络选项卡中查看请求和响应? –

回答

1

它看起来像你有交叉原点请求的问题。
页面主机(localhost:4200)与目标不同(localhost:5000)。

当发生这种情况铬发出preflighted request

不同于简单的请求(上面讨论的),“预检”请求第一 发送由OPTIONS方法的HTTP请求发送到资源上 其他域,在为了确定实际请求是否安全 发送。跨站点请求以这种方式进行预检,因为它们可能会对用户数据产生影响 。

你从那里服务器获得响应不包括需要CORS headers,并为此铬不发出实际POST请求。

+0

我相信你是对的。总是让我感到简单的事情。 – Jhorra

1

正如前面提到的Chrome发布预冲的请求。 要绕过,您可以安装this Chrome extension以启用CORS并将*'Allow-Control-Allow-Origin:'添加到您的标题。这对localhost:8000上的django和localhost:4200上的angular2起作用。