我的API在 api.domain.com
中运行,前端角度应用程序在 frontend.domain.com
下运行
CSRF implementation
-
在我的
api.domain.com
上启用了CORS,只允许从frontend.domain.com
访问 . -
CSRF令牌在名为
X-CSRFTOKEN
的自定义响应头中设置 -
在Angular应用程序中,首先它将发出获取CSRF令牌的请求,并将其附加到每个
post
请求的请求标头
//get CSRF token
$http.get("http://localhost:3000/").then(function (response) {
console.log(response.headers('X-CSRFTOKEN'));
var request = {
method: "POST",
url: 'http://localhost:3000/csrftest',
headers: {
"CSRF-Token": response.headers('X-CSRFTOKEN')
}
}
//post request with CSRF token in header
$http(request).then(function (res) {
console.log(res);
}, function (err) {
console.log(err);
})
}, function (err) {
console.log("Error", err);
});
一个缺点是,我需要为每个请求获取CSRF令牌,因此每个请求都需要额外的 $http
调用,因为CSRF令牌正在更改每个请求(无论如何都要克服这个额外的http调用?)
我的问题是在跨域应用程序中添加CSRF保护的正确方法是什么?
1 回答
有没有办法克服这个额外的HTTP调用?
在我看来(或者我认为是一般做法),在应用程序开始时,您应该进行一次CSRF调用,并且您的服务器应该设置一个包含CSRF令牌的cookie(因此您需要修改服务器代码以生成当前用户会话的单个CSRF令牌,应该对整个用户会话有效 .
然后,在Angular应用程序中,定义请求拦截器,您可以读取该cookie并将其设置为每个POST请求的HTTP头 .
在这里阅读更多:https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token
For example :(使用现有代码在响应头中传递令牌)
假设您的服务器每次都为现有会话使用相同的CSRF令牌 .
在
run
块中,点击API并获取令牌并将其存储在localStorage
中:然后添加一个拦截器并修改POST请求以添加该令牌:
现在,您的每个POST请求都将被截获,并且将设置CSRF令牌 .
我需要一个CSRF令牌的DRY代码
但是如果你想要一个DRY代码,你想在每个POST请求之前进行额外的HTTP调用来获取CSRF令牌,那么也可以使用拦截器或服务 .
使用拦截器:
来自docs:
现在,在代码中的任何地方,只需直接调用API,拦截器将负责提取新的CSRF令牌并将其设置为当前请求: