【1030 | Day56】钓鱼网站背后的秘密,原来是你(csrf)
目录
1. 跨站请求伪造(csrf)
今天第一次听说钓鱼网站的存在是基于跨站请求伪造的原理做出来的,感觉很新奇。
其实就类似于你搭建了一个跟银行一模一样的web页面,用户在你的网站转账的时候输入用户名、密码、对方账户,银行里面的钱确实少了,但是发现收款人也变了。
很不可思议吧,居然偷梁换柱、暗度陈仓!!!
其实背后的原理说白了也很简单:
- 你写的form表单中,用户的用户名 、密码,都会真实的提交给银行后台
- 但是收款人的账户却不是用户填的
- 我们实际填写的input框是一个没有name属性的input框(oh 真该死 小白吃黄连)
- 内部人员提前写好了一个隐藏的带有name和value的input框
俗话说,上有政策下有对策,码畜的头也不是白秃的!
来了,来了,你要的解决钓鱼网站的方案来了。
解决钓鱼网站的策略:
- 只要是用户想要提交post请求的页面,我在返回给用户的时候,就提前设置好一个随机字符串
- 当用户提交post请求的时候,我会自动先取查找是否有该随机字符串
- 如果有,正常提交
- 如果没有,直接报403
2. csrf装饰器
from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie
csrf_exempt # 某个视图不需要进行csrf校验
csrf_protect # 某个视图需要进行csrf校验
ensure_csrf_cookie # 确保生成csrf的cookie
2.1 csrf_exempt
只有两种装饰的方式:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
# 第一种
@method_decorator(csrf_exempt, name='dispatch')
class MyCsrf(View):
# 第二种
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
2.2 csrf_protect
除了csrf_exempt之外,所有的其他装饰器在CBV上面都有三种方式:
@method_decorator(csrf_protect,name='post')
class MyCsrf(View):
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')
3. csrf功能
csrf中间件中执行process_request
- 从cookie中获取到csrftoken的值
- csrftoken的值放入到 request.META
执行process_view
-
查询视图函数是否使用csrf_exempt装饰器,使用了就不进行csrf的校验
-
判断请求方式:
-
如果是GET', 'HEAD', 'OPTIONS', 'TRACE',不进行csrf校验
-
其他的请求方式(post,put),进行csrf校验
-
获取cookie中csrftoken的值
-
获取csrfmiddlewaretoken的值
能获取到 ——》 request_csrf_token
获取不到 ——》 获取请求头中X-csrftoken的值 ——》request_csrf_token
比较上述request_csrf_token和cookie中csrftoken的值,比较成功接收请求,比较不成功拒绝请求。
-
-
csrf校验
#form表单
#你在写的时候只需要加上一个
{% csrf_token %}
#ajax
第一种
#自己再页面上先通过{% csrf_token %}获取到随机字符串 然后利用标签查找
data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
第二种
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
第三种
拷贝js文件
OK,结束,你困了吗?
....
我....
其实...
也....
我当然不困!!!