我有两个 Web 应用程序,一个用于 AngularJS 中的 Web UI,另一个用于 Java 中的 REST Web 服务。两者都部署在不同的域上。
应用程序使用 cookie 进行身份验证。每当用户输入有效的用户名和密码时,服务器都会返回一个包含 token 的仅 http cookie,并且该 cookie 会在所有请求中传递。我在两个应用程序上都启用了 CORS,这就是 session cookie 正常工作的原因。
现在,我正在尝试为此添加 CSRF 保护。我试图使用 csrf cookie,服务器中将发送 csrf cookie(不是 httponly)作为 REST 响应的一部分,UI 将从 cookie 中读取值并将其传递到 csrf token header 中以供其他 REST 调用。
我面临的这种方法的问题是,由于服务器位于不同的域中,我无法在 AngularJs 中使用 $cookies 读取 cookie。有没有办法读取该 cookie 的值? 如果没有,那么我可以通过其他方式实现 CSRF 吗?
我还尝试在浏览器中的 Web UI 本身上实现 csrf cookie 的创建,但浏览器不会将 cookie 发送到 Web 服务,因为它位于不同的域中。
那么,我的问题是,对于这种情况如何实现csrf保护?
最佳答案
您的做法是正确的:
I also tried to implement the creation of the csrf cookie on the Web UI itself in the browser but the browser does not send the cookie to the webservice as its in different domain.
CSRF cookie 并不是要“发送”到服务器,而是要由客户端读取,然后在自定义 HTTP 请求 header 中提供。来自其他域的伪造 GET 请求(由 HTML 标记触发,如 <img src="">
)无法设置自定义 header ,因此您可以通过以下方式断言该请求来自您域上的 javascript 客户端。
以下是如何实现您正在研究的想法,假设您有 api.domain.com
和ui.domain.com
:
1) 用户从 ui.domain.com
加载 Angular 客户端
2) 用户将身份验证信息从 Angular 客户端发布到 api.domain.com
2) 使用 HttpOnly
进行回复身份验证 cookie,名为 authCookie
,以及自定义 header ,例如X-Auth-Cookie
,其中此 header 的值是链接到由 authCookie
标识的 session 的唯一值。
3) Angular 客户端读取 X-Auth-Cookie
header 值并将该值存储在 XSRF-TOKEN
中其域上的 cookie,ui.domain.com
现在你有:
-
XSRF-TOKEN
cookieui.domain.com
-
authCookie
cookieapi.domain.com
-
4) 用户在api.domain.com
上发出 protected 资源的请求。浏览器将自动提供 authCookie
值,Angular 会自动发送 X-XSRF-TOKEN
header ,并将发送从 XSRF-TOKEN
读取的值 cookies
5) 您的服务器断言 X-XSRF-TOKEN
的值链接到由 authCookie
的值标识的同一 session
我希望这有帮助!我还写过有关 Angular token 身份验证的文章,Token Based Authentication for Single Page Apps (SPAs) (免责声明:我在 Stormpath 工作)
关于angularjs - 如何实现跨域请求的csrf保护,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27793424/