2013-02-22 212 views
64

我正在处理基于客户端上的AngularJS和Java上的API(服务器端的Tomcat + Jersey)上的应用程序。HTTP头中的Set-Cookie被AngularJS忽略

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

一旦用户通过验证后,我创建在服务器端的会话

httpRequest.getSession(true);
和响应发送到客户端并在其标题中的Set-Cookie指令:

 
Set-Cookie:JSESSIONID=XXXXXXXXXXXXXXXXXXXXX; Domain=localhost; Path=/api/; HttpOnly 

的问题是, cookie从不放在客户端。当我检查cookie为localhost域时,它是空的,所以下一个请求的头中没有这个cookie,客户端仍然无法访问我的API的受限路径。

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

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

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

附加信息:在两侧都启用了CORS:

"Access-Control-Allow-Methods", "GET, POST, OPTIONS" 
"Access-Control-Allow-Origin", "*" 
"Access-Control-Allow-Credentials", true

任何有关使Set-Cookie正常工作的想法? 这是一个AngularJS相关的问题吗?

+0

我不确定它仍然是相关的,但使您的API依赖于状态是一个糟糕的设计选择(tm)。您应该让您的API无状态以避免将来出现问题。 – sberder 2013-05-10 04:24:54

+2

您是否找到解决方案?我还没有类似的问题。 – Pathsofdesign 2014-04-07 04:44:38

回答

7

此外,HttpOnly意味着浏览器不应该让插件和JavaScript看到cookie。这是安全浏览的最新约定。应该用于J_SESSIONID,但也许不在这里。

+0

即使HttpOnly属性不存在,Cookie仍未在客户端设置。 – 2013-02-22 14:33:59

+0

你确定吗?它只是**/api/**的**会话专用** cookie。一个实验是为你的链接使用'response.encodeURL'。第一个答案可能仍然使用“...?JSESSIONID = ...”而不是cookie。但随后的调用应该设置cookie。你有没有在浏览器中查看cookies? – 2013-02-22 14:53:40

+0

是的,当我使用Chrome浏览器查看Cookie是否在浏览器中设置和/或存在于请求和响应标头中时。该Cookie只有会话是。 – 2013-02-25 10:20:47

20

我找到了一个帮助我前进的issue in AngularJS

看起来"Access-Control-Allow-Credentials" : true没有在客户端设置。 指令$httpProvider.defaults.withCredentials = true被忽略。

我用配置参数中的{withCredentials:true}通过简单的$ http调用来替换$ resource调用。

+3

如果您找出解决方案,请不要忘记发布答案。如果你的客户端是移动设备,并且你正在使用phonegap/cordova或本地客户端,你是否尝试覆盖origin/refferer头文件并使用一个常量来源? – 2013-04-18 09:46:01

+1

您可以在您的后端获取来源,然后发送相关标题。以下是一个express.js示例: var origin = req.headers.origin; res.header('Access-Control-Allow-Origin',origin); – Lauris 2014-06-17 09:35:16

+5

这不是一个解决方案,而是一个问题... – 2015-11-25 16:48:34

17

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

实际上解决方案涉及到这一点和这一点。

假设你已经解决了初始发行,只能通过增加特定域的访问控制允许来源和去除通配符来解决,接下来的步骤是:

  1. 你必须从Set-Cookie头取下,只有HTTP,否则你将永远无法通过你的角码领取“生成”一个cookie
    这样的设置就已经在Firefox工作,但无法在Chrome

  2. ,使之成为Chrome浏览器也一样,你需要:

    一)从本地主机发送不同的域在cookie中,使用WS是域“托管”。你甚至可以使用类似的.domain.com代替ws.domain.com

    b通配符),那么你就需要对你的cookie指定的域的呼叫,否则Chrome浏览器不会存储您的Cookie

    [可选]我将消除/api路径赞成的/


并应到的伎俩。
希望能有一些帮助

+0

我相信问题是路径是/ api,应该是/ – 2014-01-15 17:42:40

+1

当你说“从Cookie中的本地主机发送一个不同的域,使用你的WS域”托管“”你是指前端主机还是后端主机? – Pathsofdesign 2014-04-07 05:25:35

+0

通常它应该是您的后端,但它确实取决于您的服务器体系结构。 难道你不知道你的WS在哪里吗? – domokun 2014-04-07 08:11:55

7

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

客户

$http配置withCredentialstrue通过以下方式之一:

  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

+1

不需要创建拦截器,现在你可以使用这个'$ httpProvider.defaults.withCredentials = true;' – vs4vijay 2015-06-22 09:58:43

+1

感谢您的提示! – 2015-06-23 18:04:34

11

在客户端上你的POST请求,请务必添加以下内容:

jQuery的Ajax请求:

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

具有角的$ http服务:

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

+0

我发现在我的情况下,xhrFields:{...}导致了一些问题(我的服务器响应类似未知来源*),所以我用这个而不是'beforeSend:function(xhr){xhr.withCredentials = true; }'它工作正常 – medBo 2017-09-02 04:53:45

1

刚刚解决了这样的问题。

我是这样做的,不工作...:

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

Cookies是保存在浏览器,但是当我发了新的要求,所有的小甜饼exept我的发送。 (我的Cookie是JSESSIONID)

的话,我看在Chrome检查,我发现这一点: My session are the JsessionID

的问题是,这不是正确的路径!

然后我尝试了这个,我的cookies被发送。好极了! :

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

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

问候!

+0

Greate,解决了我的问题。 – Jane 2017-06-15 07:35:01