django中间件

Posted bladecheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django中间件相关的知识,希望对你有一定的参考价值。

django中间件

什么是中间件?

django请求生命周期完整版,中间件类似于django的门卫,数据在进入和离开时都需要经过中间件

中间件能干嘛?

控制用户访问频率,全局登陆校验,用户访问白名单,黑名单等

查看django默认的三个中间件

  • Csrf
  • Session
  • Auth

中间件的使用(5个固定的方法)

自定义中间件

from django.utils.deprecation import MiddlewareMixin


class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义的中间件的process_request!')
# 写一个路由与视图,启动项目,查看打印结果。
# 再写一个自定义中间件

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第二个自定义的中间件的process_request!')
# 诠释中间件的执行顺序


# 在两个中间件中添加process_response方法。研究中间件消息进出的顺序
class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义的中间件的process_request!')
    def process_response(self,request,response):
        print('我是第一个自定义的中间件的process_response')
        return response
# 再来研究process_request中直接返回HttpReponse对象,会怎么走接下来的process_response

# process_view,process_exception,process_template_response

csrf(跨站请求伪造)

先写一个简单的post请求,复现报错信息

钓鱼网站:银行转账的路径,你是否也可以拿到,然后你做一个跟银行一模一样的页面,也超银行的借口提交数据,当用户在钓鱼网站输入对方账户名和转账金额之后,点击发送。其实内部是将对方账户换成了钓鱼网站的造假人员的账户。造成你转账转错账户的情况

开两个django项目,模拟转账的现象

如何区分钓鱼网站和正经网站?在正经网站返回页面的时候,在form表单中偷偷塞一个特殊的字符串,后端记下改页面对应的字符串的值,等用户发post请求来的时候,我先去校验特殊的字符串是否匹配

如何去写这个特殊的字符串呢?模版语法有一个固定的写法% csrf_token %,必须写在form表单内

浏览器查看改标签的值,并且每次都在刷新。再来演示刚刚转账的示例

ajax中如何设置csrf_token

# 第一种页面上先写一个%csrf_token%标签,后面用jquery查找标签取值组成键值对放入data中即可

csrf_token局部使用

# 只想给某个视图韩式加上csrf校验
from django.views.decorators.csrf import csrf_exempt,csrf_protect

# 局部禁用
@csrf_exempt
def index(request):
  pass

# 局部使用
@csrf_protect
def login(request):
  pass

# CBV比较特殊,不能单独加在某个方法上
# 只能加在类上或dispatch方法上
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@method_decorator(csrf_exempt,name='get')  # 第一种
class Csrf_Token(View):
  @method_decorator(csrf_exempt)  # 第二种
  def dispatch(self,request,*args,**kwargs):
    res = super().dispatch(request,*args,**kwargs)
    return res
  @method_decorator(csrf_exempt)  # 这里这么写不行!!!
  def get(self,request):
    pass
  def post(self,request):
    pass

Auth认证模块

执行数据库迁移的那两条命令时,即使我们没有建表,django是不是也会创建好多张表?我们创建之后去看一下里面的一个叫auth_user表,既然是表,那肯定应该有对应的操作改表的方法

auth_user表记录的添加

  • 创建超级用户(不可手动插入,因为密码是加密的)

  • 简单使用auth认证

    from django.contrib import auth
    def login(request):
      if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request,username=name,password=pwd)
        # 类似于user=models.User.objects.filter(username=name,password=pwd).first()
        if user:
          return redirect('/home/')
      return render(request,'login.html')
  • 只是简单的验证信息不行,还需要给当前成功登陆的用户保存登陆状态,之前是通过cookie或者session,现在呢,auth也给你提供了一个比较好用的方法

    if user:
      # 等价于request.session['name']=name
      auth.login(request,user)  # 登陆,其实就把用户信息放到session中,跑一下验证session表
  • 上面的验证和登陆其实不是它的亮点,亮点在于

    # 只要登陆成功执行了auth.login(request,user)
    # 之后在其他任意的视图函数中都通过request.user获取当前登陆用户对象
    
    # 当没有执行auth.login,request.user打印出来的是匿名用户。将session表数据删除即可演示改效果
    # 如何判断request.user用户是否通过auth.login登陆呢?request.user.is_authenticated
    
    # 为何执行auth.login之后,其他视图函数中就可以通过request.user拿到当前登陆对象呢?想想django的中间件中有没有一个叫Auth啥的中间件,它干了件什么事,能不能推导一下?取出session去表里面查相应的数据,然后放到request.user中,点进去看一下这个中间件确实如此
  • 注销

    auth.logout(request)
    # 等价于删除session数据request.session.flush()
  • 装饰器校验是否登陆及跳转

    from django.contrib.auth.decorators import login_required
    
    @login_required(login_url='/login/',redirect_field_name='old')  # 没登陆会跳转到login页面,并且后面会拼接上你上一次想访问的页面路径/login/?next=/test/,可以通过参数修改next键名
    def my_view(request):
      pass
  • 如果我所有的视图函数都需要装饰并跳转到login页面,那么我需要写好多份

    # 可以在配置文件中指定auth校验登陆不合法统一跳转到某个路径
    LOGIN_URL = '/login/'  # 既可以局部配置,也可以全局配置
  • 回到最上面,我们是怎么对auth_user表添加数据的?命令行输入~~~合理不?

    from django.contrib.auth.models import User
    def register(request):
      User.objects.create()  # 不能用这个,因为密码是明文
      User.objects.createuser()  # 创建普通用户
      User.objects.createsuperuser()  # 创建超级用户
  • 校验密码,修改密码

    request.user.check_password(pwd)  # 为什么不直接获取查,因为前端用户输入的是明文数据库密文
    
    request.user.set_password(pwd)
    request.user.save()  # 修改密码

自定义模型表应用auth功能

如何扩张auth_user表?

  • 一对一关联(不推荐)

    from django.contrib.auth.model s import User
    
    class UserDetail(models.Models):
      phone = models.CharField(max_length=11)
      user = models.OnoToOneField(to=User)
  • 面向对象的继承

    from django.contrib.auth.models import User,AbstractUser
    class UserInfo(AbstractUser):
      phone = models.CharField(max_length=32)
    
    # 需要在配置文件中,指定我不再使用默认的auth_user表而是使用我自己创建的Userinfo表
    AUTH_USER_MODEL = "app名.models里面对应的模型表名"
    
    
    """
    自定义认证系统默认使用的数据表之后,我们就可以像使用默认的auth_user表那样使用我们的UserInfo表了。
    库里面也没有auth_user表了,原来auth表的操作方法,现在全部用自定义的表均可实现
    """

以上是关于django中间件的主要内容,如果未能解决你的问题,请参考以下文章

Django学习之七:Django 中间件

Django中间件

Django中间件

Django之中间件

17_django中间件的使用

Django----中间件详解