最近使用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();
});
说明:
前端:
/*正常的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 {
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]
}
]