AngularJS 在 POST 请求中验证 CSRF Token

30

我正在使用AngularJS和Rails。我有以下请求,用于批量更新用户。

 $http{
    method: 'POST',
    url: $scope.update_url,
    params: {selected_ids: userIds}
 }

由于URL长度的限制(http://support.microsoft.com/kb/208427),这不能是一个“GET”请求。

但对于“POST”请求,我们需要在头部中设置CSRF认证令牌。

如何将CSRF Token设置到POST请求的头部?

3个回答

68

你可以按照$http服务中的说明设置HTTP标头。

你可以全局设置它:

$httpProvider.defaults.headers.post['My-Header']='value'   (or)
$http.defaults.headers.post['My-Header']='value';

或者对于单个请求:

$http({
   headers: {
      'My-Header': 'value'
   }  
});

这里有一个来自Angular的重要引用:

跨站请求伪造(XSRF)保护。 XSRF是一种未经授权的网站可以获取用户私人数据的技术。 Angular提供以下机制来对抗XSRF。在执行XHR请求时,$http服务从名为XSRF-TOKEN的cookie中读取令牌,并将其设置为HTTP头X-XSRF-TOKEN。由于只有运行在您域上的JavaScript才能读取cookie,因此您的服务器可以确信XHR来自在您域上运行的JavaScript。

要利用此功能,您的服务器需要在第一个HTTP GET请求中设置一个可由JavaScript读取的会话cookie中的令牌,称为XSRF-TOKEN。在随后的非GET请求中,服务器可以验证cookie是否与X-XSRF-TOKEN HTTP头匹配,因此可以确定仅运行在您域上的JavaScript才能读取该令牌。该令牌必须对于每个用户都是唯一的,并且必须由服务器进行验证(以防止JavaScript编写自己的令牌)。我们建议使用带有盐的站点身份验证cookie的摘要作为令牌,以增加安全性。


2
我不清楚为什么这个解决方案符合Angular的文档。文档说明你需要设置一个cookie,但你似乎正在手动设置头文件。 - RevNoah
@asgoth 我不确定这如何对抗 CSRF。我认为 CSRF 起作用是因为从另一个浏览器页面调用同一域会重新发送与该域关联的 cookie。如果我们将令牌放在 cookie 中,那么这个检查不就变得无用了吗? - uriDium
@RevNoah,顶部的代码示例是设置$http服务头文件的通用示例。如果cookie令牌已设置,则Angular会自动设置标头。 - Ben Fischer
@uriDium它可以对抗CSRF攻击,因为cookie令牌与请求头不同。请求头称为X-XSRF-TOKEN。尽管所有请求都会发送cookie,但它只有一个名为XSRF-TOKEN的令牌,服务器并不关心它。将cookie令牌复制到请求头的唯一方法是如果您可以读取cookie,而其他域上的页面无法执行此操作。这就是为什么这种方法有效的原因。 - Ben Fischer
在Angular中,我会在app.run()中注入CSRF_TOKEN并设置标头:$http.defaults.headers.common ['CSRF_TOKEN'] = CSRF_TOKEN... 此外,我为所有请求(POST/GET)设置它。只需确保您的GET查询不超过1024个字符即可。 - Spock
显示剩余5条评论

1

0

我最近遇到了同样的问题,通过添加gem angular_rails_js解决了它。据我理解,它会为每个Rails控制器创建一个带有Rails CSRF-TOKEN的cookie,这将被Angular $http捕获(默认$http行为)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接