Django中 前端post方式ajax传json数据 通过csrf机制
介绍一下csrf
csrf是跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
漏洞的成因就是网站的cookie在浏览器中不会过期,只要不关闭浏览器或者退出登录,那以后只要是访问这个网站,都会默认你已经登录的状态。而在这个期间,攻击者发送了构造好的csrf脚本或包含csrf脚本的链接,可能会执行一些用户不想做的功能(比如是添加账号等)。这个操作不是用户真正想要执行的。
问题描述
1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
解决方式大致分为两类:
一种是取消csrf防御机制类
在模块上添加@csrf_exempt
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def login(request):
if request.method == 'POST' :
print('可以直接post')
return render(request,'login.html')
全局设置过滤csrf
就是setting配置文件里把’django.middleware.csrf.CsrfViewMiddleware’,删掉
不取消csrf防御机制类
-
前台用{% csrf_token %}传到后台
方法前端用ajax时,请求头增加一句
headers:{'X-CSRFToken': csrf},
正常不用ajax的post传输是在form表单里添加{% csrf_token %},添加之后运行时template会自动把它转换成
<input type="hidden" name="csrfmiddlewaretoken" value="aqYPU74oA3swVzZMOPlEdh4Tle2cM4hI8kvuwKL1sdBFgWH98sqzb9svOPv1DmMb">
所以用ajax传的时候可以直接用属性选择器把这个标签的value值获取传到后台即可解决
代码展示:前提是在form表单里添加{% csrf_token %}
//ajax部分:
var loginUsername = $('#loginUsername').val();
var loginPassword = $('#loginPassword').val();
//主要是这条-----------------------------------------------------------------------
var csrf = $("input[name='csrfmiddlewaretoken']").val();
var params = {};
params.loginUsername = loginUsername;
params.loginPassword = loginPassword;
var loginLoadIndex = layer.load(2);
$('#loginBtn').val("正在登录...");
$.ajax({
type:'post',
url:window.location.protocol+'//'+window.location.host+'/user/login/',
dataType:'html',
//还有这个-------------------------------------------------
headers:{'X-CSRFToken': csrf},
data:JSON.stringify(params),//这是将数据json格式转换
contentType:'application/json',
success:function (data) {
layer.close(loginLoadIndex);
var jsonData = JSON.parse(data);
if (jsonData.code == '999'){
window.location.href = '/showdata/index/';
}
},
error:function () {
layer.close(loginLoadIndex);
$('#loginBtn').val("登录");
}
});
view部分:
#用这条接收前台传过来的json数据
request_data = request.body
print(request_data)
request_dict = json.loads(request_data.decode('utf-8'))
username = request_dict.get('loginUsername')
password = request_dict.get('loginPassword')
浙公网安备 33010602011771号