67

我正在开发一个基于客户端的 AngularJS 和服务器端的 API(Tomcat + Jersey for WS)的应用程序。

我的 API 的某些路径受到限制,如果用户没有会话,则返回的响应状态为 401。在客户端,拦截 401 http 状态以将用户重定向到登录页面。

用户通过身份验证后,我在服务器端创建一个会话

httpRequest.getSession(true);
并且发送给客户端的响应在其标头中确实包含 Set-cookie 指令:

设置 Cookie:JSESSIONID=XXXXXXXXXXXXXXXXXXXXX;域=本地主机;路径=/api/; HttpOnly

问题是cookie永远不会放在客户端。当我检查 localhost 域的 cookie 时,它​​是空的,因此下一个请求的标头中没有这个 cookie,客户端仍然无法访问我的 API 的受限路径。

客户端和服务器在同一个域中,但它们没有相同的路径和相同的端口号:

客户 :http://localhost:8000/app/index.html

服务器 :http://localhost:8080/api/restricted/

附加信息:双方都启用了 CORS:

“访问控制允许方法”、“GET、POST、OPTIONS”
“访问控制允许来源”,“*”
“访问控制允许凭据”,真

使 Set-cookie 正常工作的任何想法?它是 AngularJS 相关的问题吗?

4

6 回答 6

21

I found an issue in AngularJS that help me to move forward.

It seems that "Access-Control-Allow-Credentials" : true was not set on the client side. Instruction $httpProvider.defaults.withCredentials = true was ignored.

I replace $resource call by a simple $http call with {withCredentials:true} in the config parameter.

于 2013-02-25T16:43:59.093 回答
18

我已经设法解决了一个与您的问题非常相似的问题。我的游戏!后端尝试设置我无法在 Angular 中捕获或通过浏览器存储的会话 Cookie。

实际上,解决方案涉及到这个和那个。

假设您已经解决了最初的问题,只能通过将特定域添加到 Access-Control-Allow-Origin 并删除通配符来解决,接下来的步骤是:

  1. 您必须从Set-Cookie标头中删除 HTTP-Only,否则您将永远无法接收由您的角度代码“生成”的 cookie
    此设置已在 Firefox 中有效,但在 Chrome 中无效

  2. 要使其也适用于 Chrome,您需要:

    a) 使用您的 WS “托管”的域,在 cookie 中从 localhost 发送不同的域。你甚至可以使用通配符.domain.com代替ws.domain.com

    b) 然后您需要调用您在 cookie 中指定的域,否则 Chrome 将不会存储您的 cookie

    [可选] 我会删除该/api路径以支持/


这应该是诀窍。
希望能有所帮助

于 2013-10-31T10:55:56.897 回答
14

在客户端的发布请求中,确保添加以下内容:

对于 jquery ajax 请求:

$.ajax({
  url: "http://yoururlgoeshere",
  type: "post",
  data: "somedata",
  xhrFields: {
    withCredentials: true
  }
});

使用 Angular 的 $http 服务:

$http.post("http://yoururlgoeshere", "somedata", {
  withCredentials: true
});

于 2015-11-19T14:34:13.253 回答
9

您需要在服务器端和客户端工作。

客户

通过以下方式之一将$httpconfig设置withCredentials为:true

  1. 根据请求

    var config = {withCredentials: true};
    $http.post(url, config);
    
  2. 对于所有请求

    angular.module("your_module_name").config(['$httpProvider',
      function($httpProvider) {
        $httpProvider.interceptors.push(['$q',
          function($q) {
            return {
              request: function(config) {
                config.withCredentials = true;
                return config;
              }
            };
          }
        ]);
      }
    ]);
    

服务器

将响应标头设置Access-Control-Allow-Credentialstrue.

于 2015-06-02T17:39:02.540 回答
8

添加HttpOnly意味着浏览器不应该让插件和 JavaScript 看到 cookie。这是最近用于更安全浏览的约定。应该用于 J_SESSIONID 但可能不在此处。

于 2013-02-22T14:22:11.873 回答
2

刚刚解决了这样一个问题。

我正在这样做但没有工作......:

  $cookies.put('JSESSIONID', response.data);

Cookies 保存在浏览器中,但是当我发送一个新请求时,所有的 Cookies 都被发送了,除了我的。(我的 cookie 是 JSESSIONID)

然后我查看了 chrome 检查器,我发现了这个: 我的会话是 JsessionID

问题是那不是正确的路径!!!

然后我尝试了这个,我的 cookie 被发送了。耶!:

$cookies.put('JSESSIONID', response.data, {'path':'/'});

我不知道这是否是你的情况,但这对我有用。

问候!

于 2016-05-20T20:13:45.957 回答