如何实现跨域请求的csrf保护

Posted

技术标签:

【中文标题】如何实现跨域请求的csrf保护【英文标题】:how to implement csrf protection for cross domain requests 【发布时间】:2015-03-03 19:27:50 【问题描述】:

我有两个 Web 应用程序,一个用于 AngularJS 中的 Web UI,另一个用于 Java 中的 REST Web 服务。两者都部署在不同的域上。

应用程序使用 cookie 进行身份验证。每当用户输入有效的用户名和密码时,服务器都会返回一个包含令牌的仅 http cookie,并且该 cookie 会在所有请求中传递。我在两个应用程序上都启用了 CORS,这就是会话 cookie 正常工作的原因。

现在,我正在尝试为此添加 CSRF 保护。我试图使用csrf cookie,服务器将发送csrf cookie(不是httponly)作为REST响应的一部分,UI将从cookie中读取值并将其传递给其他REST调用的csrf令牌头。

我面临的这种方法的问题是,由于服务器位于不同的域中,我无法在 AngularJs 中使用 $cookies 读取 cookie。有没有办法读取那个 cookie 的值? 如果没有,那我可以通过其他方式实现 CSRF 吗?

我还尝试在浏览器中实现在 Web UI 本身上创建 csrf cookie,但浏览器不会将 cookie 发送到不同域中的 web 服务。

那么,我的问题是如何针对这种情况实施 csrf 保护?

【问题讨论】:

【参考方案1】:

Angularjs 内置了对 CSRF 的支持,但不幸的是它不能跨域工作,所以你必须自己构建。

我设法通过首先在第一个请求的标头和 cookie 中返回一个随机令牌来使其工作。为了阅读标题,您需要将其添加到Access-Control-Expose-Headers。然后将其添加到所有帖子中

$http.get('url').
    success(function(data, status, headers) 
        $http.defaults.headers.post['X-XSRF-TOKEN'] = headers('XSRF-TOKEN');
    );

然后在服务器上你可以将cookie值与header中的值进行比较,以确保它们相同。

【讨论】:

我试过了,因为服务器来自不同的域,我不认为 AngularJs 能够读取那个 cookie。我手动尝试并检查,对象 $cookies 中没有 cookie。我该如何解决这个问题?我还检查了 AngularJS CSRF 的链接,其中提到不会为跨域请求设置标头 我更新了我的答案。如果这不能解决您的问题,请告诉我?【参考方案2】:

$http docs:Angular 提供了一种机制来对抗 XSRF。执行 XHR 请求时,但不会为跨域请求设置。

这是一个小库,可能会对你有所帮助https://github.com/pasupulaphani/angular-csrf-cross-domain

【讨论】:

【参考方案3】:

你在正确的轨道上:

我还尝试在浏览器中实现在 Web UI 本身上创建 csrf cookie,但浏览器不会将 cookie 发送到不同域中的 web 服务。

CSRF cookie 并不是要“发送”到服务器,而是要由客户端读取,然后在自定义 HTTP 请求标头中提供。来自其他域的伪造 GET 请求(由 html 标记,例如 <img src=""> 触发)无法设置自定义标头,因此您可以通过这种方式断言请求来自您域中的 javascript 客户端。

您可以通过以下方式实现您正在研究的想法,假设您有api.domain.comui.domain.com

1) 用户从 ui.domain.com 加载 Angular 客户端

2) 用户将身份验证信息从 Angular 客户端发布到 api.domain.com

2) 服务器回复一个名为authCookieHttpOnly 身份验证cookie 和一个自定义标头,例如X-Auth-Cookie,其中此标头的值是链接到由 authCookie 标识的会话的唯一值

3) Angular 客户端读取 X-Auth-Cookie 标头值并将该值存储在其域上的 XSRF-TOKEN cookie 中,ui.domain.com

所以现在你有:

XSRF-TOKENui.domain.com 上的 cookie authCookieapi.domain.com 上的 cookie

4) 用户在api.domain.com 上请求受保护的资源。浏览器将自动提供authCookie 值,Angular 将自动发送X-XSRF-TOKEN 标头,并将发送它从XSRF-TOKEN cookie 中读取的值

5) 您的服务器断言X-XSRF-TOKEN 的值链接到由authCookie 的值标识的同一会话

我希望这会有所帮助!我还写过关于 Angular 令牌身份验证的文章,Token Based Authentication for Single Page Apps (SPAs)(免责声明:我在 Stormpath 工作)

【讨论】:

第三步,api.domain.com发送的cookie如何被ui.domain.com读取,它们在不同的域中。 @11thdimension - 在第 3 步中,ui.domain.com 上的 SPA 正在读取自定义标头“X-Auth-Cookie”,而不是读取 cookie“authCookie”本身,它不仅是第三方cookie 还有“httpOnly”

以上是关于如何实现跨域请求的csrf保护的主要内容,如果未能解决你的问题,请参考以下文章

CSRF 跨域

跨域?如何解决?同源策略?

Django网络安全跨站点请求伪造保护,CSRF如何正确使用

跨域如何解决,什么是同源策略转发

CSRF(跨域请求伪造)

如何禁用我网站中特定页面的 csrf 保护?