csrf简介与策略
为了避免钓鱼网站的漏洞,csrf要求发送请求的时候服务端响应时会分配一个随机字符串给客户端,当客户端第二次发送请求的时候携带上一次分配到的随机字符串到服务端进行校验
1.CSRF中间件
django中间件作用于整个项目,CSRF校验就是django中间件的其中之一对全局的所以视图函数或视图类起作用如果将其注释的话则就是所有的都不校验
2.form表单请求
form请求的CSRF校验只需加一个模版语法即可通过校验,也是最简单的一种使用方法语法格式如下:
<form action="" method"post"> {% csrf_token %} <!-- 模版语法--> </form>
3.Ajax请求
Ajax请求也需要用CSRF来校验,方式有多种
方式一:
<!--方式1--> {% csrf_token %} <button id="d1">Ajax请求</button> <script> $('#d1').click(function () { $.ajax({ url:'', type:'post', // 先编写csrf模版语法 在利用标签查找和值获取 data:{'username':'haha','csrfmiddlewaretoken':$('[name="csrfmifflewaretoken"]').val()}, success:function (args){ } } }
方式二:
<!--方式2--> <button id="d1">Ajax请求</button> <script> $('#d1').click(function () { $.ajax({ url:'', type:'post', // 直接利用模版语法即可 引号不能省 data:{'username':'haha','csrfmiddlewaretoken':'{{csrf_token }}'}, success:function (args){ } } }
方式三:
方式三是一种通用的方法需要编写js,先创建静态文件夹(在django配置文件中配置一下静态文件路径)再创建js文件,js代码无需我们自己编写官方就已经提供了
<!--在网页中引入编写好的js文件--> <script scr="/static/csrf.js"></script>
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); } } });
CBV添加装饰器方法
有时候我们需要针对性的对几个请求需要校验几个不需要,如果靠通过注释中间件的话会导致其所有的统一不校验或者统一全部校验,在FBV与CBV中具体的方式有所不同
1.针对FBV中的校验
csrf_protect:校验csrf
csrf_exempt:不校验csrf
# 第一步需要先导包 from django.view.decorators.csrf import ccsrf_protect,csrf_exempt # 用法很简单针对是否需要校验在函数上面加上装饰器即可 # 如果注释了CSRF中间件又想校验下面函数需要加装饰器 @csrf_protect def login(request): return HttpResponse('登陆') # 如果没有注释CSRF中间件又不想校验下面函数需要加装饰器 @csrf_exempt def login(request): return HttpResponse('登陆')
2.针对CBV中的校验
针对CBV我们不能直接在类上面直接加装饰器 需要借助专门给CBV添加装饰器的方法同时也有好几种不同的方法:
方式一:
通过给CBV添加装饰器的方法直接在方法上指名道姓的添加,这种方式只能用于添加csrf_protect对csrf_exempt无效
class MyHome(views.View): def get(self,request): return HttpResponse('Get') @method_decorator(csrf_protect) # 校验post方法 def post(self,request): return HttpResponse('Post')
方式二:
在定义类上面提前添加好那些方法需要校验,这个方式同样也不能用来添加csrf_exempt
@method_decorator(csrf_protect,name='post') # 提前指定 class MyHome(views.View): def get(self,request): return HttpResponse('Get') def post(self,request): return HttpResponse('Post')
方式三:
直接影响类中所有的方法同时支持csrf_protect与csrf_exempt
class MyHome(views.View): # @method_decorator(csrf_protect) @method_decorator(csrf_exempt) def dispatch(self,request,*args,**kwargs): super(MyHome,self).dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse('Get') def post(self,request): return HttpResponse('Post')
ps:针对csrf_exempt只有方式3有效,针对其他装饰器上述三种方式都有效
auth模块简介
auth模块是强大的django自带的一个用户认证模块,我们在开发网站的时候不可避免的需要用到用户的登录、注册等功能有了auth模块可以给我们带来更快的编写功能,django在执行数据库迁移命令后会产生一个auth_user表配合auth模块做用户认证,该表还是django admin后台管理默认的表
# admin后台管理员账号创建 python manage.py createsuperuser
auth模块常见功能:
# 1.创建用户 from django.contrib.auth.models import User User.object.create_user(username,password) # 注意创建管理员一定要加上邮箱 User.object.create.superuser(username,password,email)
from django.contrib import auth # 导入模块 # 校验用户名和密码是否正确 auth.authenticate(request,username,password) # 用户登录 auth.login(request,user_obj) # 判断用户是否登录 request.user.is_authecticated # 获取登录用户对象 rquest.user # 校验密码是否正确 request.user.check_password(old_password) # 修改密码 request.user.set_password(new_password) # 修改完记得保存 request.user.save() # 注销登录 auth.logout(request)
auth给我们提供了装饰器工具,用来快捷的给某个视图添加登录校验,如果用户没有登录则会跳转到django默认的URL '/accounts/login/ ',如果需要自定义登录的URL则需要在配置文件settings.py中通过LOGIN_URL进行修改
from django.contrib.auth.decorators import login_required @login_required def My_view(request): pass # 跳转局部配置 login_request(login_url='/login/' # 跳转全局配置 LOGIN_URL = '/login/'
auth_user表切换
# 1.models.py from django.contrib.auth.models import AbstractUser class Userinfo(AbstractUser): '''扩展auth_user表中没有的字段''' phone = models.BigIntegerField() desc = models.TextField() # 2.settings.py AUTH_USER_MODEL = 'app01.Userinfo'