Django之csrf中间件及auth模块使用
一、基于配置文件的编程思想
反射
通过字符串操作类和函数
1. importlib 模块
importlib模块可以通过字符串取出其对应的模块。
import importlib
res = 'lib.bbb'
# 利用字符串的形式导入模块
md = importlib.import_module(res)
# from lib import bbb md相当于bbb
print(md) # 该模块字符串最小单位只能到文件名
2. 配置文件
当我们导入一个模块的时候,我们其实是在导入这个模块文件夹中的__init__.py
文件。
该文件中可以导入配置文件中的配置信息。
我们在配置文件中提前将导入其他模块的具体路径写成字符串的形式,保存成配置信息。
然后在__init__.py
文件中通过importlib模块将导入的配置文件的中的配置信息字符串解析成真正的模块路径进行导入。
这样我们就可以在配置文件中输入字符串来进行模块的导入啦!而且如果我们有一些模块及功能不需要用到时,我们直接将配置文件中的路径字符串注释掉就行了。
二、跨站请求伪造(csrf)
1.csrf简介以及由来
Cross—Site Request Forgery:跨站请求伪造
有些钓鱼网站会写成与正规网站一样的界面,诱导用户使用并提交数据。当钓鱼网站接收到用户本来想发送到正规网站的数据后,钓鱼网站将这组信息进行一些修改,将其关键信息改成自己想要的数据,再把这组修改后的网站发送给正规网站进行处理。
这样钓鱼网站就达到了窃取用户信息并从中牟利的目的。这样就会使得用户与正规网站遭受损失。
为了防止这样的情况,正规网站对接受的数据做了一些处理。规定本网站只会处理自己本页面提交的post请求。
这样就可以保证从钓鱼网站发过来的跨站请求失效。
而csrf就是用来进行这样的操作的中间件。通过这个中间件,后端在向前端发送HTML页面时,会在form表单里添加一个具有name属性的input框,并且value是用户登录的真实账户,然后将这个标签隐藏。
这样用户在提交数据时,后端就可以校验你是否有这个隐藏标签,如果有,就说明你是真实用户。如果没有,就说明是其他网站发送的伪造请求。
这样就可以做到保证用户权益的目的了。
2.Django中的csrf中间件如何使用
csrf中间件在配置文件中已经写好,如果不将该中间件注释,它会自动帮后端朝前端发送HTML文件时,加入csrf_token。
这时前端再想向后端发送数据,就必须要携带csrf_token校验参数,使前端数据通过后端的csrf校验。
2.1 普通form表单提交数据
前端如何携带csrf_token:
{# 你只需要在表单中写一个{% csrf_token %} #}
<form action="" method="post">
{% csrf_token %}
{# csrf_token必须写在form表单里面 #}
<p>username:<input type="text" name="username"></p>
<p>target_account:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
2.2 ajax提交数据
方式1:较为繁琐
先在页面任意的位置上书写{% csrf_token %};
然后在发送ajax请求的时候通过标签查找获取随机字符串,添加到data自定义对象即可。
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
// 第一种
data:{
'username':'jason',
'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
},
success:function (data) {
alert(data)
}
})
})
</script>
方式2:较为简单
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
// 第二种
data:{
'username':'jason',
'csrfmiddlewaretoken':'{{ csrf_token }}' {# 要加一下引号 #}
}, {# 要加一下引号 #}
success:function (data) {
alert(data)
}
})
})
</script>
方式3:官网提供文件(最通用的一种方式)
直接新建js文件拷贝代码,导入即可;
你不需要做任何的csrf相关的代码书写
你不需要做任何的csrf相关的代码书写
<script src="/static/setup.js"></script>
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
// 第三种 利用脚本文件 啥也不用写
data:{'username':'jason'},
success:function (data) {
alert(data)
}
})
})
</script>
3.csrf相关的装饰器
3.1 csrf_exempt
如果中间件设置了需要全局校验csrf,那么该装饰器可以让函数不进行校验。
# @csrf_exempt # 不校验 csrf
def index(request):
return HttpResponse('index') # 不需要也可以交互
3.2 csrf_protect
如果csrf中间件被注释掉了,设置了全局不校验csrf,那么该函数可以
@csrf_protect # 校验
def login(request):
return HttpResponse('login')
3.3 如何在CBV的函数中使用上面两个函数
- csrf_exempt这个装饰器只能给dispatch装才能生效;
- csrf_protect任何方式都可以,和普通的装饰器装饰CBV一致。
# @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
@method_decorator(csrf_exempt,name='dispatch') # 可以
class MyIndex(views.View):
# @method_decorator(csrf_exempt) # 可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
# @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
def post(self,request):
return HttpResponse('OK')
# @method_decorator(csrf_protect,name='post') # 可以
class MyIndex(views.View):
@method_decorator(csrf_protect) # 可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
# @method_decorator(csrf_protect) # 可以
def post(self,request):
return HttpResponse('OK')
三、Django auth管理
Auth模块是Django自带的用户认证模块。
有django帮我们做登录认证,很多东西都不用自己写了,真的很开心呢!
用户数据会储存在数据迁移时,Django自动帮我们创建的auth_user表中。
1. auth模块常用方法
1.1 创建用户
想要使用auth创建用户需要先从django.contrib.auth.models
导入user
模块:
from django.contrib.auth.models import User
# 不可用 密码不是加密的
# User.objects.create(username=username,password=password)
# 创建普通用户 密码自动加密
User.objects.create_user(username=username,password=password)
# 创建超级用户 需要邮箱数据 密码自动加密
User.objects.create_superuser(username=username,password=password,email='123@qq.com')
# 源码
def create_user(self, username, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(username, email, password, **extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
1.2 校验用户名和密码
想要使用auth校验用户名和密码需要先从django.contrib
导入auth
模块:
from django.contrib import auth
user_obj = auth.authenticate(request,username=username,password=password)
# 必须传用户名和密码两个参数 缺一不可
如果该用户未找到则user_obj返回none。
1.3 保存用户登录状态
使用auth.login(request,user_obj)
保存用户登录状态,自动在user_session表中记录。
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)
# print(user_obj)
if user_obj:
# print(user_obj)
# print(type(user_obj))
# 保存用户登录状态,在session表中保存用户
# 相当于request.session['user'] = 'name'
# 且只要执行了这一句话,
# 之后你可以在任意位置通过request.user获取到当前登录用户对象
auth.login(request,user_obj)
return HttpResponse('登陆成功!')
return render(request,'login.html')
1.4 判断当前用户是否登录
使用request.user.is_authenticated()
判断用户是否登录,返回布尔值,True/False。
def check_login(request):
if request.user.is_authenticated():
return HttpResponse('login')
else:
return HttpResponse('not login')
1.5 校验原密码是否正确
通过request.user.check_password(旧密码)
来校验用户是否输入了正确的密码,返回值为布尔值True/False。
@login_required # 局部登录跳转页面配置
def check_password(request):
user_obj = request.user # 获取已经登陆的用户
if request.method == 'POST':
old_password = request.POST.get('old_password')
new_password = request.POST.get('new_password')
# 校验原来的密码是否正确 返回布尔
is_right = user_obj.check_password(old_password)
if is_right:
user_obj.set_password(new_password)
user_obj.save()
return HttpResponse('修改成功!')
return render(request,'change_password.html')
1.6 修改密码
通过request.user.set_password(新密码)
来修改用户的密码,修改完成后需要执行request.user.save()
来将修改后的数据写入数据库。
不然数据只是在缓存中修改了一下,没有真正写入数据库。
@login_required # 局部登录跳转页面配置
def check_password(request):
user_obj = request.user # 获取已经登陆的用户
if request.method == 'POST':
old_password = request.POST.get('old_password')
new_password = request.POST.get('new_password')
# 校验原来的密码是否正确 返回布尔
is_right = user_obj.check_password(old_password)
if is_right:
# 修改用户密码,并保存
user_obj.set_password(new_password)
user_obj.save()
return HttpResponse('修改成功!')
return render(request,'change_password.html')
1.7 注销
直接通过auth.logout(request)
方法注销用户。
@login_required
def logout(request):
auth.logout(request)
return HttpResponse('用户已注销!')
1.8 校验用户是否登录装饰器
1.首先需要导入登录认证装饰器模块函数
from django.contrib.auth.decorators import login_required
2.然后可以设置未登录时跳转到登录页面的url
局部配置
@login_required(login_url='/login/')
def func(request):
pass
全局配置 (settings配置文件中 直接配置)
# settings中配置
LOGIN_URL = '/login/'
# views
@login_required
def func(request):
pass
注意:
如果全局配置了,局部也配置,将以局部的login_url
为准。
2. 扩展auth_user表中的字段
2.1 利用一对一建立外键关系表
另写一张表用来存放需要添加的字段,用一对一的关系外键绑定到auth_user表上。
绑定之前需要把from django.contrib.auth.models import User
自动创建的表导过来。
# models
from django.contrib.auth.models import User
class UserDetail(models.Model):
phone = models.BigIntegerField()
user = models.OneToOneField(to='User')
2.2 继承Django提供的auth类
在创建所有表之前直接修改本应该有的auth_user表。
通过继承User表的父类,自己重写新的User类。
继承之前同样需要将User父类from django.contrib.auth.models import AbstractUser
导过来。
# models
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
phone = models.BigIntegerField()
register_time = models.DateField(auto_now_add=True)
注意:
自己重写类后,需要在配置文件中配置一下,不然系统不知道你要自己重写表了。
写完之后,之前所有的auth模块功能也全都可以通过你新写的表使用。
# settings
AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名
Django之csrf中间件及auth模块使用的更多相关文章
- Django框架之中间件与Auth
Django框架之中间件与Auth模块一 cbv加装饰器 -先导入:from django.utils.decorators import method_decorator -1 可以在方法上加装饰器 ...
- Django 中CSRF中间件 'django.middleware.csrf.CsrfViewMiddleware',
1.Django中CSRF中间件的工作原理及form表单提交需要添加{% csrf_token %}防止出现403错误 CSRF # 表示django全局发送post请求均需要字符串验证功能:防止跨站 ...
- django中间件和auth模块
Django中间件 由django的生命周期图我们可以看出,django的中间件就类似于django的保安,请求一个相应时要先通过中间件才能到达django后端(url.views.template. ...
- Django CBV加装饰器、Django中间件、auth模块
一. CBV加装饰器 在视图层中,基于函数的视图叫FBV(function base views),基于类的视图叫CBV(class base views).当需要用到装饰器时,例如之前的基于Cook ...
- 中间件和auth模块
中间件 1.什么是中间件 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用,用 ...
- Django 自带认证功能auth模块和User对象的基本操作
一.auth模块 from django.contrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: authenticate() ...
- Django的csrf中间件
csrf中间件 csrf 跨站请求伪造 补充两个装饰器: from django.views.decorators.csrf import csrf_exempt,csrf_protect ...
- python框架之Django(12)-认证系统之auth模块
我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Django作为一个完美主义者的终极框 ...
- Django 认证系统 cookie & session & auth模块
概念 cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. cookie的工作原理是:由服务器产生内容,浏 ...
随机推荐
- ThreadLocal全面解析,一篇带你入门
===================== 大厂面试题: 1.Java中的引用类型有哪几种? 2.每种引用类型的特点是什么? 3.每种引用类型的应用场景是什么? 4.ThreadLocal你了解吗 5 ...
- hbase Master is initializing
重装hbase后导致出险问题:hbase(main):007:0> create 'test_t2','f1' ERROR: org.apache.hadoop.hbase.PleaseHold ...
- A - A Gifts Fixing
t组询问,每次给出数列长度n 以及两个长度为n的数列{ai}和{bi}. 有三种操作:ai−1, bi−1以及ai,bi同时− 1 -1−1. 问最少多少步以后可以让两个数列变成常数数列. ...
- 2019-2020 ACM-ICPC Brazil Subregional Programming Contest (11/13)
\(2019-2020\ ACM-ICPC\ Brazil\ Subregional\ Programming\ Contest\) \(A.Artwork\) 并查集,把检测区域能在一起的检测器放在 ...
- hdu5550 Game Rooms
Time Limit: 4000/4000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submission ...
- Codeforces Round #547 (Div. 3) C. Polycarp Restores Permutation (数学)
题意:有一长度为\(n\)的序列\(p\),现在给你\(q_i=p_{i+1}-q_i \ (1\le i\le n)\),问你是否能还原出原序列,如果能救输出原序列,否则输出\(-1\). 题解:由 ...
- NYOJ746——整数划分(四)
描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷..亲爱的你能帮帮他吗? 问题是我们经常见到的整 ...
- Codeforces Round #531 (Div. 3) E. Monotonic Renumeration (构造)
题意:给出一个长度为\(n\)的序列\(a\),根据\(a\)构造一个序列\(b\),要求: 1.\(b_{1}=0\) 2.对于\(i,j(i\le i,j \le n)\),若\(a_{i ...
- synchronized底层原理
synchronized底层语义原理 Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现. 在 Java 语言中,同步用的最多的地方可能是被 syn ...
- 信号量解决理发师问题(barber)
问题描述及思路 代码 一些细节见注释 这里ret应该用int..忘了改了. 运行结果 因为座位数和到来最大间隔的原因,没有出现全部椅子被占用的情况