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;

    }

}