csrf跨站请求伪造
(1)介绍
-
钓鱼网站
- 我搭建一个跟正规网站一模一样的界面(中国银行)
- 用户不小心进入我们的网站,用户给某个人打钱
- 打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了
- 但是唯一不同的是打钱的账户不是用户想要转过去的账户
-
内部本质
- 在钓鱼网站的页面,针对对方账户,只给用户提供一个没有name属性的普通input框
- 然后再内部隐藏一个已经写好name和value的input框
-
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
-
当这个页面朝后端发送post请求的时候 后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden) 如果成功则正常执行
(2)如何符合校验
- form表单放在任意地方
<h1>我是正经网站</h1>
<form action="" method="post">
{% csrf_token %}
<p>username: <input type="text" name="username"></p>
<p>target_user: <input type="text" name="target_user"></p>
<p>money<input type="text" name="money"></p>
<input type="submit">
<input type="submit" value="ajax请求">
</form>
- ajax校验方式
- 第一种 利用标签查找获取页面上的随机字符串
<script>
$('#b1').click(function (){
$.ajax({
url: '',
type:'post',
data:{'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
success:function (){
}
})
})
</script>
- 第二种 利用模版语法提供的快捷书写
<script>
$('#b1').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'csrfmiddlewaretoken': '{{ csrf_token }}'},
success: function () {
}
})
})
</script>
- 第三种 通用方式 导入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);
}
}
});
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'mysetup.js' %}"></script>
</head>
<body>
<h1>我是正经网站</h1>
<form action="" method="post">
<p>username: <input type="text" name="username"></p>
<p>target_user: <input type="text" name="target_user"></p>
<p>money<input type="text" name="money"></p>
<input type="submit">
<input type="submit" value="ajax请求" id="b1">
</form>
</body>
<script>
$('#b1').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'username': 'heart'},
success: function () {
}
})
})
</script>
</html>
(3)csrf相关装饰器
-
网站整齐都不校验csrf,就单单几个视图需要校验
-
网站整体都校验csrf,就单单几个视图函数不校验
from django.views.decorators.csrf import csrf_protect,csrf_exempt
"""
csrf_protect 需要校验 把中间件注释
csrf_exempt 忽视校验 把中间件打开
"""
(1)csrf_protect 需要校验
- FBV直接写在函数上即可
@csrf_protect
@csrf_exempt
def transefer(request):
if request.method == 'POST':
username = request.POST.get('username')
target_user = request.POST.get('target_user')
money = request.POST.get('money')
print(f'{username}给{target_user}转了{money}元')
return render(request, 'transefer.html')
- CBV和之前用装饰器的方法一样
from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.views import View
from django.utils.decorators import method_decorator
# 第二种方式
@method_decorator(csrf_protect,name='post')
class MyCsrfToken(View):
# 第三种方式
def dispatch(self, request, *args, **kwargs):
return super(MyCsrfToken, self).dispatch(request, *args, **kwargs
def get(self,request):
return HttpResponse('get')
# 第一种方式
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')
(2)csrf_exempt 忽视校验
- 只能给dispatch方法加才有效
from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.views import View
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
# 只能给dispatch方法加才有效
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(MyCsrfToken, self).dispatch(request, *args, **kwargs
def get(self,request):
return HttpResponse('get')
def post(self,request):
return HttpResponse('post')
标签:function,跨站,return,name,request,校验,csrf,伪造
From: https://www.cnblogs.com/ssrheart/p/18103142