CSRF装饰器与基于中间件注册思想编写项目与auth认证模块


目录
  • CSRF相关装饰器
  • 通过字符串导入模块
  • 基于中间件注册思想编写项目
  • auth认证模块
  • auth模块方法
  • auth扩展表字段

CSRF相关装饰器

关于CSRF有两个装饰器:

from django.views.decorators.csrf import csrf_exempt, csrf_protect
  • csrf_exempt:用于忽略CSRF校验的装饰器
  • csrf_protect:用于开启CSRF校验的装饰器

csrf_exempt

这个一般用于使用了CSRF的中间件的时候,因为使用了CSRF中间件相当于给所有视图函数开启了CSRF校验,这个装饰器就是为了给某个视图函数忽略CSRF校验用的。

csrf_protect

这个一般用于没有使用CSRF的中间件的时候,因为所有视图函数都没有开启了CSRF校验,这个装饰器就是为了给某个视图函数开启CSRF校验用的。

针对FBV使用

两个装饰器都可以直接在函数上方添加

@csrf_exempt
def index(request):
    return HttpResponse()

针对CBV使用

csrf_protect:三种CBV添加装饰器的方式都可以
csrf_exempt:只有给重写的dispatch方法装饰可以生效

class MyView(views.View):
    def get(self, request):
        return HttpResponse()
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

通过字符串导入模块

通过中间件的配置文件看到:

很显然这些都是一个个模块,这种通过字符串导入模块的方式是因为使用了importlib模块,这个模块可以把字符串的路径导入。

导入模块

import importlib

使用:

module_path = 'aaa.c'
importlib.import_module(module_path)

等价于常规导入方式:

from aaa import c

这个模块有一个缺点:最小导入单位是模块文件级别,也就是无法导入模块文件名称空间中的名称。既无法单独导入py文件中的变量名、函数名、类名等。

基于中间件注册思想编写项目

我们编写完自定义中间件后需要去配置文件中进行注册,这个功能就会自动添加到项目中,那么我们该如果实现这种相同效果呢?

现在想要实现一个功能:不动运行文件,只创建一个方法,并把这个方法配置在配置文件中,就可以执行内部代码。

我们已发送信息模拟。

首先创建如下文件:

email.py:

class Email:
    def send(self, msg):
        print('邮箱发送了:%s' % msg)

phone.py:

class Phone:
    def send(self, msg):
        print('短信发送了:%s' % msg)

qq.py:

class QQ:
    def send(self, msg):
        print('QQ发送了:%s' % msg)

settings.py:

SETTINGS = [
    'aaa.email.Email',
    'aaa.phone.Phone',
    'aaa.qq.QQ',
]

start.py:

import importlib
from settings import SETTINGS

def send_all(msg):
    # 1.循环配置文件中的路径
    for str_path in SETTINGS:
        # 2.切割路径,比如'aaa.qq.QQ'切割成'aaa.qq'与'QQ'
        module_name, str_class_name = str_path.rsplit('.', maxsplit=1)
        # 3.导入模块
        module = importlib.import_module(module_name)
        # 4.利用反射获取模块内名称空间的名称
        class_name = getattr(module, str_class_name)
        # 5.实例化
        obj = class_name()
        # 6.调用对象里面的方法
        obj.send(msg)

if __name__ == '__main__':
    send_all('666')

auth认证模块

django给我们提供了一个可以快速完成用户相关功能的模块,那就是auth认证模块,包含用户创建、认证、编辑等。

也提供了一张用户表,这张表是在我们执行数据库迁移命令之后默认产生的:auth_user表,里面记录了用户的各种信息。

创建django自带的路由url(r'^admin/', admin.site.urls)就是参考这张表的信息认证的。

其中is_superuser字段就是判断这个用户是否是管理员用的,我们可以自己创建一个管理员。

进入run manage.py task终端,输入:

createsuperuser

然后按照提示信息输入就可以了,这时候我们就可以访问django自带的admin路由去登录了。

随便一提,auth_user中的密码是经过加密处理后保存的,有更高的安全性。

auth模块方法

要使用auth模块首先要导入:

from django.contrib import auth  # 主要模块
from django.contrib.auth.models import User  # 用户表

创建普通用户:根据auth_user表添加,username字段必填

User.objects.create_user(username=,)

创建管理员用户:根据auth_user表添加,username、password、email字段必填

User.objects.create_superuser(username=,password=,email=)

验证用户名和密码是否正确:返回一个用户对象,可以获取其他字段信息,用户名和密码错误返回None。

user_obj = auth.authenticate(request,username=username,password=password)

保存用户登录状态:自动帮你操作session相关

auth.login(request, user_obj)

获取当前用户对象:返回当前登录的用户对象,没有登录则返回AnonymousUser对象,里面没有信息

user_obj = request.user

判断当前用户是否登录:返回布尔值

request.user.is_authenticated()

比对密码是否与当前登录用户相同:返回布尔值

request.user.check_password('password')

修改密码:需要保存

request.user.set_password('new_password')
request.user.save()  # 同步到数据库中

注销当前已登录用户:即删除seesion

auth.logout(request)

校验登录装饰器

导入:

from django.contrib.auth.decorators import login_required

局部配置:login_url即未登录用户跳转的路由地址

@login_required(login_url='/login/')

全局配置:默认跳转到/accounts/login/

@login_required

可以在settings.py配置文件中配置全局:

LOGIN_URL = '/login/'  # 在配置文件中添加路由地址

auth扩展表字段

如果想要在原有的auth_user表上扩展表字段,有两种方式:

方式一:编写一对一表关系,自己创建一张表,与auth_user建立一对一关系即可。

方式二:自己在模型层创建一个类去继承auth的用户类。

from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
    # 编写AbstractUser类中没有的字段,不能冲突
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=32)

编写完类后,还需要去settings.py配置文件里添加配置:app01是我的应用名,并且添加配置不需要写models路径

AUTH_USER_MODEL = 'app01.MyUser'

补充:

  1. 类继承之后,需要重新执行数据库迁移命令,并且库里面是第一次操作迁移命令才可以,也就是auth_user表还没有被创建之前才能生效。
  2. auth模块所有的方法都可以直接在自定义模型类上面使用,因为是继承关系。