cookie跨域问题

最近使用angular做项目,后端走cookie session认证机制,登陆接口服务端有set-cookie,后台也做了跨域处理 ,但是发起请求时浏览器请求里没有携带cookie。一直以为是angular机制引起的,然而跟angular没有关系。跨域请求由于安全性机制,默认是不携带cookie。

解决方法:前后端配合,均需要修改。

后端:

app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:4200");
    /*http://localhost:4200为跨域的域名和端口号,一定要指定*/
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Credentials", true);
    /*Access-Control-Allow-Credentials携带身份信息的凭证,其值必须为true*/
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", ' 3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

说明:

  1. Access-Control-Allow-Origin。HTTP响应头,指定服务器端允许进行跨域资源访问的来源域。可以用通配符*表示允许任何域的JavaScript访问资源,但是在响应一个携带身份信息(Credential)的HTTP请求时,Access-Control-Allow-Origin必需指定具体的域,不能用通配符。
  2. Access-Control-Allow-Credentials。HTTP响应头,凡是浏览器请求中携带了身份信息,而响应头中没有返回Access-Control-Allow-Credentials: true的,浏览器都会忽略此次响应。

前端:

/*正常的ajax请求*/
$http.post("http://a.domain.com/Api/Product", 
    { paramsId: 3 }, 
    {withCredentials: true})
    .success(function (data) {
    //TODO
});
/*angular手动封装的http*/
public getNoParamObj(url: string) {
    return this.http.get(this.serverUrl + url,new RequestOptions({withCredentials: true}))
      .map(res => res.json())
  }
前端需要指定:
withCredentials: true,

如果get请求和post请求都要携带cookie,均需要加上 withCredentials:true;或者是可以统一设置

/*angular js*/    
angular.module("app").config(function ($httpProvider) {   
 $httpProvider.defaults.withCredentials = true;
})
/*ajax请求*/
$.ajax({
    type: "POST",
    url: "http://a.domain.com/Api/Product",
    xhrFields: {
        withCredentials: true
    },
    success: function (data) {
        console.log(data)
    },
    error: function (data) {
        console.error(data)
    }
})
/*angular(未验证),需要修改http服务,然后设置withCredentials=true*/

http.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, Request, RequestOptions, Response, XHRBackend } from '@angular/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class HttpService extends Http {
  constructor(backend: XHRBackend, options: RequestOptions) {
    super(backend, options);
  }

  request(url: string | Request, options?: any): Observable<Response> {
    if (typeof url === 'string') {
        if (!options) {
            options = {headers: new Headers()};
        }
        options.withCredentials = true;
    } else {
        url.withCredentials = true;
    }

    return super.request(url, options);
  }
}
http.service.factory.ts

import { RequestOptions, XHRBackend } from '@angular/http';
import { HttpService } from './http.service';

export function HttpServiceFactory(backend: XHRBackend, defaultOptions: RequestOptions) {
  return new HttpService(backend, defaultOptions);
};
and in your module file you need to replace your http service

import { HttpServiceFactory } from './http.service.factory';
import { Http, RequestOptions, XHRBackend } from '@angular/http';

...

providers: [
  {
    provide: Http,
    useFactory: HttpServiceFactory,
    deps: [XHRBackend, RequestOptions]
  }
]

猜你喜欢

转载自blog.csdn.net/weboof/article/details/79799231