angularjs $http 服务不会在 POST 上设置 cookie,但会使用 GET
angularjs $http service doesn't set cookie on POST but does with GET
我项目的服务端提供了WebApi 2.2
客户端是用 Ionic 编写的移动应用程序
一切都在 chrome 本地运行,移动应用处于仿真模式。
1) 在服务器上启用了 CORS,并且每个 API 控制器都装饰有:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
2) angular $http 服务也配置为与 CORS 一起工作:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.common['X-FirePHP-Version'];
3) 用户通过身份验证后,我从 API 控制器发回一个 cookie:
var cookie = new CookieHeaderValue("user-id", result.Entity.ToString());
cookie.Path = "/";
cookie.HttpOnly = true;
cookie.Secure = true;
response.Headers.AddCookies(new CookieHeaderValue[]{ cookie });
我可以在响应中看到这个 cookie header:
Set-Cookie:user-id=306d5247-1d3b-4120-b412-6ce45105397a; path=/; secure; httponly
4) 在 WebApi 管道中,我注册了全局 DelegatingHandler 以读取随请求发送的 cookie
对我来说奇怪的是,当我进行 POST 调用时(此请求已预检),然后在委托处理程序中,cookie collection 为空。在将方法 AcceptVerb(在控制器和 javascript 服务中)更改为 GET 时,我的问题得到解决并且我的 cookie 存在。
我的 js 服务是:
var setData= function (model) {
var deferred = $q.defer();
var url = stringHelper.format(endpoints.setData, sessionId);
var config = {
url: url,
method: 'POST',
data: {
name: model.name,
email: model.email
}
};
$http(config).then(function (result) {
deferred.resolve(true);
}, function (error) {
$log.debug(error);
deferred.reject(error);
});
return deferred.promise;
}
重要通知:从 Postman 对同一端点进行 POST 调用可以正常工作。
有没有人有类似的问题?
谢谢
我终于想通了:
1) 在将有效的 GET 请求与失败的 POST 进行比较后,我注意到 GET 未使用 OPTIONS 进行预检,而 POST 是
2) 在 CORS 定义材料中我读到 OPTIONS 没有发送任何 cookie
作为解决方案,我在我的 DelegatingHandler 中添加了检查请求方法 - 因此它将 OPTIONS 方法向下传递到管道中,而不检查 autentifiaction cookie。
希望对某人有所帮助:)
这是我的 WebApi DelegatingHandler
:
public class UserCookieHandler : DelegatingHandler
{
static public string ServerSessionId = "server-session-id";
static public string UserSessionId = "user-session-id";
const string LoginUri = "api/secured/login/login";
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string sessionId = string.Empty;
if (request.Method != HttpMethod.Options && !request.RequestUri.PathAndQuery.Contains(LoginUri))
{
string cookie = request.GetCookie(ServerSessionId);
if (cookie == null)
{
return request.CreateErrorResponse(HttpStatusCode.Forbidden, "Please log in");
}
else
{
sessionId = cookie;
try
{
Guid guid = Guid.Parse(sessionId);
}
catch (FormatException)
{
request.CreateErrorResponse(HttpStatusCode.BadRequest, "Please log in again");
}
}
request.Properties[ServerSessionId] = sessionId;
}
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
return response;
}
}
我项目的服务端提供了WebApi 2.2 客户端是用 Ionic 编写的移动应用程序 一切都在 chrome 本地运行,移动应用处于仿真模式。
1) 在服务器上启用了 CORS,并且每个 API 控制器都装饰有:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
2) angular $http 服务也配置为与 CORS 一起工作:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.common['X-FirePHP-Version'];
3) 用户通过身份验证后,我从 API 控制器发回一个 cookie:
var cookie = new CookieHeaderValue("user-id", result.Entity.ToString());
cookie.Path = "/";
cookie.HttpOnly = true;
cookie.Secure = true;
response.Headers.AddCookies(new CookieHeaderValue[]{ cookie });
我可以在响应中看到这个 cookie header:
Set-Cookie:user-id=306d5247-1d3b-4120-b412-6ce45105397a; path=/; secure; httponly
4) 在 WebApi 管道中,我注册了全局 DelegatingHandler 以读取随请求发送的 cookie
对我来说奇怪的是,当我进行 POST 调用时(此请求已预检),然后在委托处理程序中,cookie collection 为空。在将方法 AcceptVerb(在控制器和 javascript 服务中)更改为 GET 时,我的问题得到解决并且我的 cookie 存在。
我的 js 服务是:
var setData= function (model) {
var deferred = $q.defer();
var url = stringHelper.format(endpoints.setData, sessionId);
var config = {
url: url,
method: 'POST',
data: {
name: model.name,
email: model.email
}
};
$http(config).then(function (result) {
deferred.resolve(true);
}, function (error) {
$log.debug(error);
deferred.reject(error);
});
return deferred.promise;
}
重要通知:从 Postman 对同一端点进行 POST 调用可以正常工作。
有没有人有类似的问题? 谢谢
我终于想通了:
1) 在将有效的 GET 请求与失败的 POST 进行比较后,我注意到 GET 未使用 OPTIONS 进行预检,而 POST 是
2) 在 CORS 定义材料中我读到 OPTIONS 没有发送任何 cookie
作为解决方案,我在我的 DelegatingHandler 中添加了检查请求方法 - 因此它将 OPTIONS 方法向下传递到管道中,而不检查 autentifiaction cookie。
希望对某人有所帮助:)
这是我的 WebApi DelegatingHandler
:
public class UserCookieHandler : DelegatingHandler
{
static public string ServerSessionId = "server-session-id";
static public string UserSessionId = "user-session-id";
const string LoginUri = "api/secured/login/login";
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string sessionId = string.Empty;
if (request.Method != HttpMethod.Options && !request.RequestUri.PathAndQuery.Contains(LoginUri))
{
string cookie = request.GetCookie(ServerSessionId);
if (cookie == null)
{
return request.CreateErrorResponse(HttpStatusCode.Forbidden, "Please log in");
}
else
{
sessionId = cookie;
try
{
Guid guid = Guid.Parse(sessionId);
}
catch (FormatException)
{
request.CreateErrorResponse(HttpStatusCode.BadRequest, "Please log in again");
}
}
request.Properties[ServerSessionId] = sessionId;
}
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
return response;
}
}