Django CSRF与auth模块
Posted ygzico
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django CSRF与auth模块相关的知识,希望对你有一定的参考价值。
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表了
以上是关于Django CSRF与auth模块的主要内容,如果未能解决你的问题,请参考以下文章
Django对中间件的调用思想csrf中间件详细介绍Django settings源码剖析Django的Auth模块
Django CBV装饰器 中间件 auth模块 CSRF跨站请求