django之CSFR
django之CSFR
CSRF是什么?
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,
通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,
XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比
,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
django CSRF
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
- @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
默认django的CSRF 是开启的 在settings中
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 认为用户提交的数据都是不安全的,所以会利用一个认证机制来防御这种攻击的方式。
首先我们新建一个页面如下:
urlpatterns = [ path('/',views.login), path('admin/', admin.site.urls), url(r'^login/',views.login), ]
views中
def login(request): if request.method=='GET': return render(request,'lgoin.html') elif request.method=="POST": user=request.POST.get('user') pwd=request.POST.get('pwd') if user=='root' and pwd=='123': request.session['username']=user request.session['is_login']=True if request.POST.get('rmb',None)=='1': # 超时时间 request.session.set_expiry(10) return redirect('/index/') else: return render(request, 'lgoin.html')
在login.html 中如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> <input type="text" name="user"> <input type="password" name="pwd"> <input type="submit" value="登陆" /> <input id="btn" type="button" value="按钮" /> </form> </body> </html>
提交访问一下是一个403页面
那么怎么去做一个安全的页面呢?
打开网络中。发现cookies中有 CSRFtoken 这个东西。那么这个东西是怎么来的
那么这个东西是怎么来的。首先说下原理。当get请求服务器的之后,服务器会随机发一个字符串给你,存在cookies 中。
就是为了做一个认证的方式,GET请求的时候是正常的。只有POST请求的时候发送数据服务端才会做认证
现在我们是FROM提交的。那么提交的时候一定需要是带有这个token的,才能提交成功。如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> {% csrf_token %} <input type="text" name="user"> <input type="password" name="pwd"> <input type="checkbox" name="rmb" value="1">10秒免登陆 <input type="submit" value="登陆" /> <input id="btn" type="button" value="按钮" /> </form> </body> </html>
加入一个{{% csft_token %}}
再次提交一下:
看一下cookies
这边已经成功了。
那么如果发起ajax 怎么去处理呢。
HTML如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> {% csrf_token %} <input type="text" name="user"> <input type="password" name="pwd"> <input type="checkbox" name="rmb" value="1">10秒免登陆 <input type="submit" value="登陆" /> <input id="btn" type="button" value="按钮" /> </form> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $(function () { $.ajaxSetup({ beforeSend:function (xhr,settings) { xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken')); } }); var csrftoken=$.cookie('csrftoken'); $('#btn').click(function () { $.ajax({ url:'/login/', type:'POST', data:{ 'user':'root','pwd':'123' }, success:function (arg) { } }) }) }) </script> </body> </html>
点击
成功提交了ajax请求。
总结:
1. from 提交
{% csrf_token %}
2. ajax提交
$(function () { $.ajaxSetup({ beforeSend:function (xhr,settings) { xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken')); } }); var csrftoken=$.cookie('csrftoken'); $('#btn').click(function () { $.ajax({ url:'/login/', type:'POST', data:{ 'user':'root','pwd':'123' }, success:function (arg) { } }) }) })
csrf_protect和csrf_exempt 应用
如果说你需要单个views 不设置csrf如下:
例如index
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt def index(request): # 获取当前用户的随机字符串 # 根据随机字符串获取对应的信息 # if request.session.get('is_login',None): return render(request,'index.html',{'user':request.session['username']}) else: return HttpResponse('<a href="/login">登陆</a>')
如果需要改成 csrf_protect
len
2019年12月17日 下午5:33
应该是form提交,你好像2个地方写成from提交了。