我有一个Django webapp,它既有前端的,可通过Web访问的组件,也有桌面客户端访问的API.但是,现在使用新的CSRF中间件组件,来自桌面客户端的POST请求的API请求将获得403.
我理解为什么会发生这种情况,但在不影响安全性的情况下解决这个问题的正确方法是什么?有没有我可以在HTTP标头中发出信号,它是一个API请求,Django不应该检查CSRF或者这是一个糟糕的策略?
编辑 -
我目前使用的方法是桌面客户端设置标头,X-Requested-With:XMLHttpRequest.这有点像hacky,但我不确定如何更好地处理它.
我不明白使用"挑战令牌"会增加任何形式的预防:应该将什么价值与什么相比较?
来自OWASP:
通常,开发人员只需为当前会话生成一次此令牌.在初始生成此令牌之后,该值将存储在会话中,并用于每个后续请求,直到会话到期为止.
如果我正确理解了这个过程,就会发生这种情况.
我在http://example.com登录,并创建包含此随机令牌的会话/ cookie.然后,每个表单都包含一个隐藏的输入,该输入也包含会话中的这个随机值,在表单提交时与会话/ cookie进行比较.
但那取得了什么成果呢?您是不是只是将会话数据放入页面,然后将其与完全相同的会话数据进行比较?似乎像循环推理.这些文章一直在谈论遵循"同源策略",但这没有任何意义,因为所有CSRF攻击都与用户起源相同,只是诱使用户采取他/她不打算采取的行动.
除了将令牌作为查询字符串附加到每个URL之外,还有其他选择吗?看起来非常丑陋且不切实际,并且使用户的书签更难.
我在我的django应用程序中有一个流程,我将用户重定向到另一个服务(例如PayPal),该服务经过一些自己的处理后,将用户返回到我自己的服务器上.我的服务器上的返回点是一个简单的HTML成功页面,我使用direct_to_template进行渲染.
由于某些奇怪的原因,另一个服务器发送POST请求,因此用户看到CSRF令牌丢失错误,因为另一个服务器不发回任何CSRF令牌.
如何从CSRF令牌中免除direct_to_template视图?
我一直在使用API实现Rails 4应用程序.我希望能够通过手机和webapp本身调用API.我在研究时遇到了这个问题protect_from_forgery:
重要的是要记住XML或JSON请求也会受到影响,如果您正在构建API,则需要以下内容:
class ApplicationController < ActionController::Base
protect_from_forgery
skip_before_action :verify_authenticity_token, if: :json_request?
protected
def json_request?
request.format.json?
end
end
Run Code Online (Sandbox Code Playgroud)
我想这样做,但我有一些保留/问题:
onclick发布JSON 的javascript 创建链接?handle_unverified_requestapi令牌存在且当前用户正确的情况下恢复,该怎么办?编辑以澄清:
我更关注webapp用户点击精心设计的CSRF链接.移动用户经过身份验证,授权,拥有API密钥,因此我并不关心它们.但是,通过为webapp用户启用CSRF保护,移动用户将无法使用受保护的API.我想知道处理这个的正确策略,我不相信Rails文档给出了正确的答案.
我正在处理单页应用程序,我正在使用Laravel 5进行Web服务.
所有表单都是异步提交的,我在它们上面使用了一个beforeSend来附加我从meta标签中获取的CSRF令牌,如下所示:
$.ajax({
url: '/whatever/route',
type: 'POST',
dataType: 'JSON',
data: $('form#whatever-form').serialize(),
beforeSend: function(request) {
return request.setRequestHeader('X-CSRF-Token', $("meta[name='token']").attr('content'));
},
success: function(response){
rivets.bind($('#whateverTag'), {whateverData: response});
},
error: function(response){
}
});
Run Code Online (Sandbox Code Playgroud)
我的所有表单都运行正常但dropzone上传却没有.它给了我一个TokenMismatchException例外.这是我的dropzone代码来更新个人资料照片:
$("#mydropzone").dropzone({
url: "/profile/update-photo",
addRemoveLinks : true,
maxFilesize: 5,
dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>  <h4 class="display-inline"> (Or Click)</h4></span>',
dictResponseError: 'Error uploading file!'
});
Run Code Online (Sandbox Code Playgroud)
我也试过把它beforeSend放在这里:
$("#mydropzone").dropzone({
url: "/profile/update-photo",
addRemoveLinks : true,
maxFilesize: 5,
dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block …Run Code Online (Sandbox Code Playgroud) 我正在尝试从CSRF保护应用程序(php和许多JS).
我想用令牌.
很多操作都是用AJAX完成的,所以我必须在Javascript中传递令牌.如果我想为每个会话或每页加载生成1个令牌,那么它很简单 - 我生成新令牌,将其放在DOM中的某个位置,然后使用Javascript找到它并发送到处理端.
但是,如果我想为每个操作使用新令牌呢?我正在考虑做一个ajax调用来重新生成令牌,然后将结果传递给处理页面.
这会增加安全风险吗?我正在考虑引诱用户使用脚本来寻求令牌,然后使用它来发出请求,然后再次跨域Javascript被禁止.它可以用闪光灯完成吗?
也许另一种保护来自CSRF的ajax调用的方法?
谢谢!
有什么需要使用<meta>将CSRF令牌名称和值放在<head>标记内:
例如:
<meta content="authenticity_token" name="csrf-param" />
<meta content="4sWPhTlJAmt1IcyNq1FCyivsAVhHqjiDCKRXOgOQock=" name="csrf-token" />
Run Code Online (Sandbox Code Playgroud)
我已经阅读了关于将CSRF值保留在cookie中的概念,但没有找到保留在<head>标记内的原因.
在我的django应用程序中,我在数据库中存储html字符串,然后将在用户的主页上显示为"消息".其中一些消息包含表单,但没有用模板语言编写,我无法插入csrf令牌(因此破坏了应用程序).
有没有办法直接从我正在编辑的python文件中插入此标记?我正在寻找以下内容:
csrf_token = django.csrf.generate()
message = "press the button please: <form><input type='hidden' name='csrf_token' value='%s'><input type='submit' value='press here'></form>" % (csrf_token)
Run Code Online (Sandbox Code Playgroud)
任何其他可以在类似情况下工作的解决方案都会很棒.谢谢
编辑: 实际上这不会起作用,因为每个会话的令牌都不同,因此将其存储在数据库中并不是很有用.有没有办法在视图中动态加载令牌?
我们是否必须为网站中的每个表单生成令牌?我的意思是,每次为每个请求的表单生成不同的令牌?如果没有,为什么?
csrf ×10
security ×5
django ×3
api ×2
ajax ×1
cookies ×1
cors ×1
django-csrf ×1
dropzone.js ×1
javascript ×1
json ×1
laravel-5 ×1
meta-tags ×1
session ×1
web ×1