Djiango:csrf跨站请求伪造
一、csrf跨站请求伪造
1.csrf简介
CSRF跨站点请求伪造Cross Site Request Forgery,是一种挟持用户在当前已登录的web应用程序上执意非本意的操作的攻击方法。
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
2.模拟钓鱼网站案例
某个钓鱼网站,从网址到页面都和真银行网站一摸一样,当你想要通过银行操作业务的时候,他会将你的银行卡号和密码发送给真的银行,但是转账人取被改成洗钱的账户(隐藏的input
框)提交给银行,然后通过真银行将钱转走。
- 后端
def transfer_func(request): if request.method == "POST": username = request.POST.get('username') transfer_name = request.POST.get('transfer_name') money = request.POST.get('money') print(f"{username}给{transfer_name}转账了{money}元") return render(request, 'transferPage.html')
-
钓鱼网站前端
通过内部隐藏标签,将用户想要转账的转账人更改
二、csrf相关校验策略
在settings中解开注释,开启csrf验证机制,当我们提交POST请求时,在提交数据的位置添加唯一标识,以供后续校验使用
1.form的csrf策略
在form表单内部添加模版语法
{% csrf_token %}
在web浏览器的页面上则会多一个input标签出来,属性name="csrfmiddlewaretoken"
,value
为随机字符串
2.ajax请求csrf策略
(1)方式1:自己手动取值,较为繁琐
在data中添加一个键值对为'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
$('.c1').click(function (){ $.ajax({ url:'', type:'post', data:{ 'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val(), 'username':'duoduo', 'transfer_name':'qiuqiu', 'money':11111, }, success:function (args){ } }) })
(2)方式2:利用模版语法自动获取(一定要用引号引起来)
在data中添加一个'csrfmiddlewaretoken':'{{ csrf_token }
,自动传一个token
$('.c1').click(function (){ $.ajax({ url:'', type:'post', data:{ 'csrfmiddlewaretoken':'{{ csrf_token }}', 'username':'duoduo', 'transfer_name':'qiuqiu', 'money':11111, }, success:function (args){ } }) })
(3)方式3:直接引入一个js脚步(官网提供的)
通过静态文件,为所有ajax
发送请求时自动添加上csrftoken
及其随机字符串。
在static
中新建一个js文件,将脚本拷贝进去,并在网页上连接进去
参考:https://www.cnblogs.com/Dominic-Ji/p/9234099.html
- csrf.js
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
三、csrf相关视图验证
需求:整个django项目都校验csrf,但是某些视图函数/类不校验csrf。
解决:使用csrf提供的装饰器
1.FBV添加csrf校验装饰器
在视图中,为某个函数单独设置需要csrf
校验,或者取消单独某个函数的csrf
校验。
需要导入以下两个模块。
from django.views.decorators.csrf import csrf_protect # 单独校验 from django.views.decorators.csrf import csrf_exempt # 取消校验
-
@csrf_exempt
当添加exempt装饰器时,就算在settings中还保存着csrf校验,该函数对应的路由地址也不会开启csrf校验
@csrf_exempt def transfer_func(request):pass
-
@csrf_protect
添加protect装饰器,则会开启csrf校验
@csrf_protect def transfer_func(request):pass
2.CBV添加csrf校验装饰器
当我们和FBV一样添加相同的装饰器给类中的函数的时候,并不会直接报错csrf验证,而是没有cookies。
所以,不能直接给在CBV中的方法添加装饰器,需要导入一个模块,通过该模块的装饰器,给CBV中的方法添加csrf校验功能
# 使用CBV的模块,CBV需要继承该类 from django.views import View # 添加csrf装饰器的模块 from django.utils.decorators import method_decorator
(1)方式1:单独生效,针对某个方法添加csrf装饰器
class ...(): @method_decorator(csrf_protect) def post():
(2)方式2:单独生效
给类中的某一个方法添加装饰器
@method_decorator(csrf_protect, name='post') class MyView(View): def post(self, request): return HttpResponse('这里是 MyView 的post')
(3)方式3:给整个类中生效
重写dispatch方法,dispatch是整个CBV方法分发的入口
class MyView(View): @method_decorator(csrf_protect) # 方式3:重写dispatch方法,为整个类中的方法添加csrf校验 def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def post(self, request): return HttpResponse('这里是 MyView 的post')
特例:csrf_exempt只有第三种方法生效,其他的不方法不支持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY