Django Ajax登录 防止CSRF
什么是CSRF
维基百科:
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
攻击细节:
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
防御措施:
检查Referer字段
HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。以上文银行操作为例,Referer字段地址通常应该是转账按钮所在的网页地址,应该也位于www.examplebank.com之下。而如果是CSRF攻击传来的请求,Referer字段会是包含恶意网址的地址,不会位于www.examplebank.com之下,这时候服务器就能识别出恶意的访问。
这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。但这种办法也有其局限性,因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。
添加校验token
由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再执行CSRF攻击。这种数据通常是表单中的一个数据项。服务器将其生成并附加在表单中,其内容是一个伪乱数。当客户端通过表单提交请求时,这个伪乱数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪乱数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪乱数的值,服务器端就会因为校验token的值为空或者错误,拒绝这个可疑请求。
Django中防范CSRF
Django的中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
其中'django.middleware.csrf.CsrfViewMiddleware',就是负责验证 csrf_token 的。
写一个简单的用户登陆
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^login/$', views.login),
url(r'^index/$', views.index),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
def login(request):
if request.method == 'POST':
username = request.POST.get('user')
password = request.POST.get('pwd')
if username == 'lcg' and password == '123':
return redirect('/index/')
return render(request, 'login.html')
def index(request):
return HttpResponse('登录成功!')
login.html
<form action="/login/" method="post">
<input type="text" placeholder="username" name="user">
<input type="password" placeholder="password" name="pwd">
<input type="submit" value="登录">
</form>
启动项目。进入login界面

当我输入用户名密码,点击登陆的时候,会报错:

下面我在login.html中加上csrf_token
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" placeholder="username" name="user">
<input type="password" placeholder="password" name="pwd">
<input type="submit" value="登录">
</form>
此时再登陆就可以成功登陆!
审查元素看一下此时的Elements与之前有何不同:

此时,其实是多了一个input框,type="hidden"属性是隐藏的功能。
我们知道,防范CSRF攻击的一个办法可以是请求的时候带一个 token,到服务器验证 token 的有效性。django 对于 csrf 的防御主要在 middleware 实现,项目的settings.py中包含 django.middleware.csrf.CsrfViewMiddleware 这个中间件,默认是开始 csrf 防御的。每次在模板里写 form 时都知道要加一个 {% csrf_token %} ,如果是Ajax请求,也要携带 这个值,否则验证不通过会报Forbidden的错。
Ajax登录:
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^login/$', views.login),
url(r'^index/$', views.index),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
import json
def login(request):
if request.method == 'POST':
username = request.POST.get('user')
password = request.POST.get('pwd')
loginResponse = {"username": None, "error_msg": None}
if username == 'lcg' and password == '123':
loginResponse["username"] = username
else:
loginResponse["error_msg"] = "username or password is wrong!"
return HttpResponse(json.dumps(loginResponse))
return render(request, 'login.html')
def index(request):
return HttpResponse('登录成功!')
login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>ajax登录</title>
</head>
<body>
{% csrf_token %}
<input type="text" placeholder="username" id="user">
<input type="password" placeholder="password" id="pwd">
<button id="btn">登录</button>
<span id="error"></span>
<script src="/static/js/jquery-3.2.1.min.js"></script>
<script>
$("#btn").on('click', function () {
$.ajax({
url: "/login/",
type: "POST",
data: {
user: $("#user").val(),
pwd: $("#pwd").val(),
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
},
success: function (arg) {
var arg = JSON.parse(arg);
if (arg.username) {
location.href = "/index/"
}
else {
$("#error").text(arg.error_msg).css("color", "red")
}
}
})
});
</script>
</body>
</html>
效果:
输入错误:

输入正确:

Django Ajax登录 防止CSRF的更多相关文章
- python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)
一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 from app01 import views urlpatterns = [ path('admin/', admi ...
- 关于Django Ajax CSRF 认证
CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的 ...
- Django 博客项目01 数据库设计与验证码校验+Ajax登录
数据库设计 from django.db import models from django.contrib.auth.models import AbstractUser class UserInf ...
- python学习-- Django Ajax CSRF 认证
使用 jQuery 的 ajax 或者 post 之前 加入这个 js 代码:http://www.ziqiangxuetang.com/media/django/csrf.js /*======== ...
- Django(十二)视图--利用jquery从后台发送ajax请求并处理、ajax登录案例
一.Ajax基本概念 [参考]:https://www.runoob.com/jquery/jquery-ajax-intro.html 异步的javascript.在不全部加载某一个页面部的情况下, ...
- Django学习系列之CSRF
Django CSRF 什么是CSRF CSRF, Cross Site Request Forgery, 跨站点伪造请求.举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果 某个用户已经登录到 ...
- 玩转Django的POST请求 CSRF
玩转Django的POST请求 CSRF 不少麻油们玩django都会碰到这个问题,POST请求莫名其妙的返回 403 foribidden,希望这篇博文能解答所有问题 三种方法 To enable ...
- Django ajax MYSQL Highcharts<1>
Another small project with django/Ajax/Mysql/Highcharts. 看下效果图 - delivery dashboard .嘿嘿 是不是还蛮好看的. 废 ...
- django ajax报错解决:You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set.
Django版本号:1.11.15 django中ajax请求报错:You called this URL via POST, but the URL doesn't end in a slash a ...
随机推荐
- 快速切题 poj1258
坑!!!我还以为一个整数会截到两行!! Agri-Net Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 40056 Ac ...
- 51nod1513
题解: 更据题意,在树上深度为没一个数的都放在一起,要用的时候二分出来,看结果 用c++的数据结构 代码: #include<bits/stdc++.h> using namespace ...
- flashfxp 命令行
以后更新软件时,尽量用bat命令行 http://www.flashfxp.com/forum/flashfxp/frequently-asked-questions-faq-/14748-comma ...
- 栈(stack),C++模板实现
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- matplotlib小示例
matplotlib 画廊 http://matplotlib.org/gallery.html import numpy as np import matplotlib.pyplot as plt ...
- iOS项目实现SVN代码管理方法③(Part 三)
内容中包含 base64string 图片造成字符过多,拒绝显示
- 离线使用Visual Studio的Javascript Prettier插件
用Prettier插件来格式化Javascript代码效果好的不得了,简直是强迫症的救命克星,可惜单位的电脑是不联网的,始终用不了,今天抽空研究了一下,找到办法了. 1.下载JavaScript Pr ...
- 简单的C#爬虫
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...
- css3实现漂亮的倒影效果
实际上还有很多CSS新属性并未包含进CSS3官方标准中.-webkit-box-reflect属性就是以谷歌浏览器为代表的Webkit渲染引擎独有的特征.-webkit-box-reflect的作用是 ...
- SWIFT解析天气JSON格式
访问以下链接可以得到京城当天的天气:http://www.weather.com.cn/adat/sk/101010100.html 返回的JSON格式如下: {"weatherinfo&q ...