Django CSRF与auth模块
CSRF
FORM表单中怎么通过CSRF校验
只需要在form表单中写一个
{% csrf_token %}
ajax通过asrf校验有三种方法
$.ajax({ url:'', type:'post', {#data:{'username':'yang'},#} //第一种方式 自己手动获取 {#data:{'username':'yang','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#} //第二种方式 利用模板语法 {#data:{'username': 'yang', 'csrfmiddlewaretoken':'{{ csrf_token }}'},#} //第三种方式 通用方式 需要引入外部js文件 data:{'username':'yang'}, success:function (data) { alert(data) } })
第三种需要引入外部js文件,文件中需要书写以下代码
写一个getCookie方法
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); } } });
将上面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)
CSRF相关装饰器
from django.views.decorators.csrf import csrf_exempt, csrf_protect
应用场景:
- 当网站整体都校验csrf的时候,想让某几个视图函数不校验
- 当网站整体都不校验csrf的时候,想让某几个视图函数校验
csrf_exempt:不校验
csrf_protect:校验
# @csrf_exempt # 不校验csrf @csrf_protect # 校验csrf def index(request): print('我是视图函数index') def render(): return HttpResponse('我是index里面的render函数') obj = HttpResponse('index') obj.render = render return obj
给FBV装饰,导入后直接加装饰器就行
但是给CBV加装饰器,有三种方式
需要导入一个方法,使用这个方法method_decorator(csrf_protect)
- 加在CBV视图的某个方法上
from django.views import View from django.utils.decorators import method_decorator class MyHome(View): def get(self, request): return HttpResponse('get') @method_decorator(csrf_protect) # 第一种方式 def post(self, request): return HttpResponse('post')
- 直接加在视图类上,但是method_decorator需要传入name关键字参数
from django.views import View from django.utils.decorators import method_decorator @method_decorator(csrf_protect, name='post') # 第二种,知名道姓的给类的某个方法装饰 class MyHome(View): def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post')
- 加在dispatch方法上
在匹配类方法之前,都需要dispatch方法分发,所以给该方法装饰,就代表整个类中的方法都是校验或不校验
from django.views import View from django.utils.decorators import method_decorator class MyHome(View): @method_decorator(csrf_protect) # 第三种 类中所有的方法都装 def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post')
CBV中首先执行的就是dispatch方法,所以这么写相当于给get和post方法都加上了登录校验。
补充
CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。
- csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
from django.views import View from django.utils.decorators import method_decorator class MyHome(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post')
or
from django.views import View from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name='dispatch') class MyHome(View): def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post')
注意:给CBV加装饰器,推荐使用模块method_decorator,csrf_exempt只能给dispatch方法装
auth模块
Django用户相关的自带的功能模块
导入模块
from django.contrib import auth from django.contrib.auth.models import User
auth模块常用方法:
1.创建用户
- create()
虽然可以创建,但是密码是明文,对后面的密码校验修改密码等功能都有影响,所以不推荐使用
User.objects.create(username='用户名',password='密码',email='邮箱',...)
- create_user()
auth提供的一个创建新用户的方法,需要提供必要参数(username, password)
User.objects.create_user(username='用户名',password='密码',email='邮箱',...)
- create_superuser()
User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
2.校验用户名和密码是否正确
- authenticate()
提供了用户认证功能,需要username 、password两个关键字参数
authenticate(username='usernamer',password='password')
注意:
- 认证成功(用户名和密码正确有效),便会返回一个 User 对象
- 认证失败(用户名和密码不正确),便会返回一个 None
3.保存用户登录状态(session)
- login()
可以实现一个用户登录的功能,需要一个HttpRequest对象,以及一个经过认证的User对象
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') user_obj = auth.authenticate(request, username=username, password=password) """ 用户名密码正确返回的是用户对象 错误的话返回的是None """ if user_obj: auth.login(request, user_obj) return HttpResponse('登录成功') return render(request, 'login.html')
只要执行了这个方法,之后在任意可以获取到request对象的地方,都可以通过request.user获取当前登录的对象
4.判断是否登录以及获取当前登录用户对象
- is_authenticated()
用来判断当前请求是否通过了认证
request.user.is_authenticated() # 返回布尔值
- request.user
获取登录用户对象
5.登录装饰器
- login_required()
auth 给我们提供的一个装饰器工具
from django.contrib.auth.decorators import login_required @login_required() def is_login(request): pass
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径).
可以自定义登录的URL,在settings.py文件中通过LOGIN_URL进行修改
# 全局配置: LOGIN_URL = '/login/' # 这里配置成你项目登录页面的路由 # 局部配置: @login_required(login_url='/login/')
若两者都配置了,优先执行局部的配置
6.判断密码是否正确
- check_password()
auth提供的一个检查密码是否正确的方法,需要传入当前请求用户的密码,返回布尔值
is_right = request.user.check_password(old_password)
7.修改密码
- set_password()
auth 提供的一个修改密码的方法,接收要设置的新密码
注意:一定要调用user.save方法保存
user.set_password(password='') user.save()
修改密码的例子
@login_required() def set_password(request): if request.method == 'POST': old_password = request.POST.get('old_password') new_password = request.POST.get('new_password') is_right = request.user.check_password(old_password)# 判断旧密码是否正确 print(is_right) if is_right: request.user.set_password(new_password) # 设置新密码 request.user.save() # save保存 return render(request, 'set_password.html')
8.注销功能
- logout()
需要一个request参数,没有返回值
当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错
@login_required() def logout(request): auth.logout(request) return HttpResponse('注销成功')
扩展默认的auth_user表
我们可以通过继承内置的AbstractUser 类,来定义一个自己的Model类,这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统
利用类的继承
from django.contrib.auth.models import User,AbstractUser class UserInfo(AbstractUser): phone = models.CharField(max_length=11, null=True) avatar = models.FileField() def __str__(self): return self.username
注意:
按上面的方式扩展了内置的auth_user表之后,要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。
写法如下:AUTH_USER_MODEL = '应用名.表名'
# 引用Django自带的User表,继承使用时需要设置 AUTH_USER_MODEL = "app名.UserInfo"
再次注意:
一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了
来源:https://www.cnblogs.com/YGZICO/p/12198766.html