我有一个项目,其中Play Framework应用程序用作Chrome扩展程序的API后端。由于我没有为Play Framework项目指定任何过滤器,因此它默认启用CSRF保护(通过CSRFFilter),这可能适用于我的情况,也可能不适用。
在Chrome扩展程序中,我首先进行jQuery AJAX调用以登录,以便Play Framework服务器设置用户令牌cookie(用于在所有后续API调用中识别用户):
$.ajax({
method: 'POST',
url: serverUrl + "api/google_sign_in",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ google_id_token: token }),
success: function (response) {
onSuccess();
},
error: function (req, status, error) {
onError(error);
}
});
调用成功,用户令牌设置为cookie。到现在为止还挺好。但是,只要我尝试使用类似的jQuery AJAX调用进行任何其他API调用,Play Framework就会抱怨缺少CSRF令牌,大概是因为现在有一个需要保护的cookie集:
[CSRF] Check failed because no token found in headers for /api/get_status
呼叫失败。根据我对CSRF保护的非常有限的理解,服务器应该在某些时候在某些生成的HTML中包含CSRF令牌?但在这种情况下,只有返回JSON的纯API调用。我是否希望在服务器返回的JSON中明确指定CSRF令牌,然后在Javascript端的以下AJAX调用中手动将其作为标头包含在内?
另外,我是否需要为此类API后端提供CSRF保护?或者我可以完全禁用它吗?
谢谢,Nir
答案 0 :(得分:1)
根据CSRF filter上的官方文档,默认情况下启用CSRF过滤器几乎任何非GET,HEAD或OPTIONS请求(例如POST或PUT),其中存在某种cookie /授权标头和CORS过滤器未配置为信任请求的来源。您有几个选项可以解决此问题:
这个很容易。进入您的路线文件,并将+ nocsrf
放在您想要免除CSRF保护的每条路线上方的行中。当您没有百万个API端点可以免除或者您没有构建SPA /公共API时,这种方法效果最佳。
Set up the CORS filter接受来自多个域的请求,它将自动绕过CSRF。
对于用户未直接使用网站的此类请求,可以假设,如果他们拥有有效的令牌,他们已经过正确的身份验证,您可以像您建议的那样禁用CSRF,您将会可能没事。请注意,CSRF确实使您的应用程序更安全,但仅限于确保不能从其他网站伪造请求。因为看起来您的API几乎无处不在,所以这不适用于您的项目。但是,如果有任何形式和控件,我会在后端服务上使用它。
编辑: According to this blog,如果你不得不担心XSS,你仍然应该使用CSRF。基于令牌的身份验证不受CSRF的影响,但如果您不小心,您仍然可能受到XSS的攻击(默认假设是没有人足够小心,并且可以使用一点额外的安全性)。确保客户端在发出请求时可以获取CSRF令牌,并将其与主登录令牌分开存储。然后在服务器上使用两者验证请求。
答案 1 :(得分:0)
我不喜欢从路线中删除XSS保护的想法。 The official documentation states :
如果您正在与 AJAX,您可以将CSRF令牌放在HTML页面中,然后添加它 使用Csrf-Token标头访问请求。
我发现this post提供了一种非常不错的方式来将CSRF令牌包含在您的ajax请求中。请务必阅读,因为以下内容仅说明完整答案的表面。
首先,请确保将@AddCSRFToken添加到控制器的方法中,该方法服务于包含发布ajax请求的JS的页面。这样可以从您的JS脚本中使用令牌。
然后在Scala模板(TWIRL)中的脚本中添加以下代码:
<script type="text/javascript">
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('Csrf-Token','@helper.CSRF.getToken.value');
}
});
</script>
这将告诉JQuery将Csrf令牌传递给您的Ajax请求,并且播放不会干扰。
$.post({
//Don't forget .url() for the js reverse routing ;)
url: jsRoutes.controllers.MyController.homePage().url,
data: {
armyId : data[i].id,
position : {
x: hex.position.x,
y: hex.position.y }
},
dataType: "json"
})
我希望这对您有帮助!