Angular2:支持 withCredentials 和 useXDomain

Posted

技术标签:

【中文标题】Angular2:支持 withCredentials 和 useXDomain【英文标题】:Angular2: Support for withCredentials and useXDomain 【发布时间】:2016-07-31 08:14:28 【问题描述】:

我是 angular2 的新手。我正在尝试从我当前正在编写前端代码的本地主机登录到我的 Django 服务器,这是一个生产服务器。另外,我正在将端口转发到我的生产服务器。 我不断收到 CORS 问题。 这是我在控制台中遇到的错误:

XMLHttpRequest 无法加载 https://www.smartkart.ca/api/user/login/。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'http://127.0.0.1:8000' 因此不允许访问。

我已经编写了我的 HTTpService 并阅读了几乎所有的博客以找出解决方案,但没有运气。我相信我需要使用 withCredentials: true 属性。我阅读了一些博客并修改了我的代码以支持 withCredentials 但没有运气。

这是我的代码 sn-p:

import Injectable from 'angular2/core';
import Http from 'angular2/http';
import 'rxjs/add/operator/map';
import Headers from 'angular2/http';
import BaseRequestOptions, RequestOptions from 'angular2/http';


@Injectable()
export class HTTPService 
constructor(private _http: Http) 



baseUrl: String = "https://www.smartkart.ca/";
getStoreList()         
    return this._http.get(this.baseUrl + 'api/current/store/')
        .map(res => res.json());
;

getCookie(name) 
    let value = "; " + document.cookie;
    let parts = value.split("; " + name + "=");
    if (parts.length == 2) 
    return parts.pop().split(";").shift();
;


login()  
    // var request = new XMLHttpRequest();
    // var params = JSON.stringify('email': 'karan@smartkart.ca', 'password': 'k0ttawa#1234');
    // request.open('POST', this.baseUrl+ "api/user/login/", true);
    // request.onreadystatechange = function() if (request.readyState==4) alert("It worked!");;
    // request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    // request.setRequestHeader("Content-length", params.length.toString());
    // request.setRequestHeader("Connection", "close");
    // request.send(params);             
    var data = JSON.stringify('email': 'test@smartkart.ca', 'password': 'blahblah');     
    var params = data;  
    var headers = new Headers ();
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Basic ' + btoa('karan@smartkart.ca:k0ttawa#1234'));
    headers.append("Content-type", "application/x-www-form-urlencoded, application/json");
    // headers.append("Content-length", params.length.toString());
    // headers.append('Access-Control-Allow-Origin', '*');
    // headers.append('Access-Control-Request-Headers', 'x-requested-with');
    // headers.append('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    // headers.append('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    // headers.append('Access-Control-Allow-Credentials', 'true');
    // headers.append('Content-Type', 'pplication/x-www-form-urlencoded');
    // headers.append('X-CSRFToken', this.getCookie('csrftoken'));

    return this._http.post(this.baseUrl+ "api/user/login/", params,
         
             headers: headers
         
    ).map(res => res.json())

;


这是我在浏览器的网络标签中看到的内容

现在,如果我删除授权标头,我确实会登录并取回 csrf 令牌,但由于 CORS 问题,我永远无法从服务器获得任何响应。这是一张快照

我阅读了一些有解决方法的博客。我也试过了,但没有成功。

这是我的解决方法代码:

import Injectable from 'angular2/core';
import BrowserXhr  from 'angular2/http';

@Injectable()
export class CORSBrowserXHr extends BrowserXhr 

build(): any 
    let xhr = super.build();
    xhr.withCredentials = true;
    return <any>(xhr);


并在引导程序中添加以下内容:

/// <reference path="../typings/browser.d.ts" />
import bootstrap from 'angular2/platform/browser';
import AppComponent from "./app.component";
import ROUTER_PROVIDERS from "angular2/router";
import APP_BASE_HREF from 'angular2/router';
import provide from 'angular2/core';
import LocationStrategy, HashLocationStrategy from 'angular2/router';
import HTTP_PROVIDERS from "angular2/http";
import BrowserXhr from 'angular2/http';
import CORSBrowserXHr from "./CORSBrowserXHr.services";

bootstrap(AppComponent, [ROUTER_PROVIDERS, HTTP_PROVIDERS,       provide(BrowserXhr, useClass:CORSBrowserXHr),
provide(LocationStrategy, useClass: HashLocationStrategy)]);

我知道 angular2 处于测试阶段,但我相信现在他们必须想出一个支持 CORS 的解决方案。如果有人有任何想法,请发表评论。

提前致谢!!

【问题讨论】:

【参考方案1】:

其实CORS主要有两种情况:

简单请求。如果我们使用 HTTP 方法 GETHEADPOST,我们就是在这种情况下。对于POST 方法,仅支持具有以下值的内容类型:text/plainapplication/x-www-form-urlencodedmultipart/form-data。即使您在这种情况下,并且如果您使用自定义标头(您自己在请求中定义的标头),您也会陷入预检请求。

预检请求。如果不是简单请求,则会执行第一个请求(使用 HTTP 方法 OPTIONS),以检查在跨域请求的上下文中可以做什么。

在您的情况下,您处于第二种情况(预检请求),因为您使用自定义标头(由您自己定义)Authorization 之一。

但是对应的 OPTIONS 请求没有在其响应中定义 Access-Control-Allow-Origin 标头。这将允许浏览器确定您(例如 localhost:3000)是否能够执行目标请求。

事实上,这不是您的 Angular2 应用程序的问题,而是您尝试访问的服务器应用程序的问题。后者应该返回适​​当的 CORS 标头,例如 Access-Control-Allow-Origin 之一。否则你的浏览器会阻止请求...

您可能会对这些文章感兴趣:

http://restlet.com/blog/2015/12/15/understanding-and-using-cors/ http://restlet.com/blog/2016/09/27/how-to-fix-cors-problems/

【讨论】:

【参考方案2】:
class MyBaseRequestOptions extends BaseRequestOptions 
  headers: Headers = new Headers(
    'X-Requested-With': 'XMLHttpRequest'
  );
  withCredentials: boolean = true;


bootstrap( AppComponent, [ provide(RequestOptions, useClass: MyBaseRequestOptions) ] );

你可以试试这个吗,来自:https://github.com/angular/angular/issues/4231

【讨论】:

我需要在引导提供程序中注入它还是可以直接在我的 httpService 构造函数中使用它? 你可以在你注入Http的主构造函数中添加Auth构造函数代码,这就足够了。 是的,试过了,没用。我直接将它添加到我的 httpservice 构造函数中 您可以为您的问题创建一个 Plunker 以便于检查吗? 当然可以。一旦我完成了 plunker 就会在这里发表评论

以上是关于Angular2:支持 withCredentials 和 useXDomain的主要内容,如果未能解决你的问题,请参考以下文章

SpreadJS 在 Angular2 中支持绑定哪些属性?

SpreadJS 全面支持 Angular2,V10.2 版本即将发布

仅 Angular2 中的协议方案问题支持跨源请求

SpreadJS 在 Angular2 中支持哪些事件?

SpreadJS 全面支持 Angular2,V10.2 版本即将发布

SpreadJS 在 Angular2 中支持绑定哪些属性?