在前面的博客中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面。我们通过给几个特定视图函数加装饰器实现了这个需求。但是以后添加的视图函数可能也需要加上装饰器,这样是不是稍微有点繁琐。
他就像相当于django的门户,通俗一点就是阻止你进门的保安,需要验证。
只要是全局相关的功能你都应该考虑使用django中间件来帮你完成
全局用户身份校验
全局用户访问频率校验
用户访问黑名单
用户访问白名单
什么是中间件:
中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。
中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法。
注意:
但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。
只要以后用django开发业务 设计到全局相关的功能 你就考虑用中间件
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',
]
中间件可以定义六个方法,分别是:(主要的是process_request和process_response)
class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
def process_response(self, request, response):
class CsrfViewMiddleware(MiddlewareMixin):
def process_request(self, request):
def process_view(self, request, callback, callback_args, callback_kwargs):
def process_response(self, request, response):
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户
请求来的时候会按照配置文件中注册的中间从上往下的顺序依次执行每一个中间件里的process_request方法,如果没有直接跳过执行下一个同级别返回,并不会全部执行process_resquest
process_request有一个参数,就是request,这个request和视图函数中的request是一样的
由于request对象是一样的,所以我们可以对request对象进行一系列的操作,包括request.变量名=变量值,这样的操作,我们可以在后续的视图函数中通过相同的方式即可获取到我们在中间件中设置的值。
它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
代码:
相应走的时候会按照配置文件中注册的中间件从下往上的顺序依次执行每一个中间件里面的process_response方法,该方法必须要有两个形参,并且需要将形参respondse返回
如果你内部自己返回了HttpResponse对象 会将返回给用户浏览器的内容替换成你自己的
路人匹配成功执行视图函数之前触发
process_view(self, request, view_func, view_args, view_kwargs)
该方法有四个参数
request是HttpRequest对象。
view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
view_args是将传递给视图的位置参数的列表.
view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。
Django会在调用视图函数之前调用process_view方法。
它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,那么将不会执行Django的视图函数,而是直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
视图函数返回的对象中必须要有render属性对应的render方法
视图函数返回的对象中必须要有render属性对应的render方法
def index(request):
print('我是视图函数index')
def render():
return HttpResponse("你好啊 我是index里面的render函数")
obj = HttpResponse("index")
obj.render = render
return obj
当视图函数报错的时候自动触发
该方法两个参数:
一个HttpRequest对象
一个exception是视图函数异常产生的Exception对象
这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。
本质搭建一个跟正常网站一模一样的页面
用户在该页面上完成转账功能
转账的请求确实是朝着正常网站的服务端提交
唯一不同的在于收款账户人不同
给用户书写form表单 对方账户的input没有name属性
你自己悄悄提前写好了一个具有默认的并且是隐藏的具有name属性的input
模拟钓鱼网站
要做一个网站跟他一样
效果:给用户转的钱到钓鱼网站的用户账上去了
解决钓鱼网站问题:
form表单如何通过csrf校验
你只需要在你的form表单内写一个
{% csrf_token %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h2>我是正儿八经的网站</h2>
<form action="" method="post">
{# {% csrf_token %}#}
<p>username:<input type="text" name="username"></p>
<p>target_user:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
<button id="d1">发送ajax请求</button>
{#{% load static %}#}
{#<script src="{% static 'myset.js' %}"></script>#}
{#<script>#}
{# $('#d1').click(function () {#}
{# $.ajax({#}
{# url:'',#}
{# type:'post',#}
{#data:{'username':'jason'},#}
{# // 第一种方式 自己手动获取#}
{#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
{# // 第二种方式 利用模板语法#}
{#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
{# // 第三种 通用方式 引入外部js文件#}
{# data:{'username':'jason'},#}
{# success:function (data) {#}
{# alert(data)#}
{# }#}
{# })#}
{# })#}
{#</script>#}
</body>
</html>
// 第一种方式 自己手动获取
{#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
// 第二种方式 利用模板语法
{#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
// 第三种 通用方式 引入外部js文件 官网提供的方式
{% load static %}
<script src="{% static 'myset.js' %}"></script>
data:{'username':'jason'}
当我们网站整体都校验csrf的时候 我想让某几个视图函数不校验
当我们网站整体都不校验csrf的时候 我想让某几个视图函数校验
给CBV加装饰器 推荐你使用模块method_decorator
我们自己写的装饰器和csrf_protect用法一致
唯独csrf_exempt是一个特例 只能给dispatch方法装
导入:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views import View9
from django.utils.decorators import method_decorator
# @method_decorator(csrf_protect,name='post') # 第二种指名道姓的给类中某个方法装
# @method_decorator(csrf_exempt,name='post') # csrf_exempt 第二种方式不行
@method_decorator(csrf_exempt,name='dispatch') # 可以!!!
class MyHome(View): # APIView
# @method_decorator(csrf_protect) # 第三种 类中所有的方法都装
# @method_decorator(csrf_exempt) # csrf_exempt 第三种方式可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('get')
# @method_decorator(csrf_protect) # 第一种方式
# @method_decorator(csrf_exempt) # csrf_exempt 第一种方式不行
def post(self,request):
return HttpResponse('post')
django用户相关的自带的功能模块 auth_user表
createsuperuser
from django.contrib import auth
from django.contrib.auth.models import User
User.objects.create() # 密码是明文
User.objects.createuser() # 基本都用它
User.objects.createsuperuser() # 邮箱要给数据
auth.authenticate(username=username,password=password) # 用户名和密码两个一个都不能少
# 该方法当用户名和密码正确的时候返回的用户对象 不正确返回None
auth.login(request,user_obj) # 这一句执行之后 request.user获取当前登录的用户对象
request.user.is_authenticated() # 判断是否登录
request.user # 登录用户对象
from django.contrib.auth.decorators import login_required
# 局部配置
@login_required(login_url='/login/')
def xxx(request):
return HttpResponse('xxx页面')
# 全局配置
配置文件中写以下代码
LOGIN_URL = '/login/'
@login_required
def xxx(request):
return HttpResponse('xxx页面')
# 如果两个都设置了 那么优先执行局部配置
request.user.check_password(old_password) # 校验原密码是否正确
request.user.set_password(new_password)
request.user.save() # 一定要保存
auth.logout(request)
# 2 利用类的继承
# 1 类的继承
from django.contrib.auth.models import User,AbstractUser
# Create your models here.
class Userinfo(AbstractUser):
phone = models.BigIntegerField()
avatar = models.FileField()
# 扩展的字段 尽量不要与原先表中的字段冲突
# 2 配置文件
AUTH_USER_MODEL = '应用名.表名'
总结:
django就会将userinfo表来替换auth_user表
并且之前auth模块所有的功能不变 参照的也是userinfo表
原文:https://www.cnblogs.com/WQ577098649/p/12194357.html