django-3-用户与权限

一、定义用户模型类

1.1 django默认用户模型类

Django认证系统中提供了用户模型类User保存用户的数据。

  • User对象是认证系统的核心。

Django认证系统用户模型类位置

  • django.contrib.auth.models.User

class User(AbstractUser):
    """
    Users within the Django authentication system are represented by this
    model.

    Username and password are required. Other fields are optional.
    """

    class Meta(AbstractUser.Meta):
        swappable = "AUTH_USER_MODEL"

父类AbstractUser介绍:

  • User对象的基本属性:
    • 创建用户(注册用户)必选:username、password
    • 创建用户(注册用户)可选: email、first_name、last_name、last_login、date_joined、 is_active 、is_staff、is_superuser
    • 判断用户是否通过认证(是否登录): is_authenticated
  • 创建用户(注册用户)的方法:
user = User.objects.create_user(username, email, password, **extra_fields)
  • 用户认证(用户登录)的方法:
from django.contrib.auth import authenticate
user = authenticate(username=username, password=password, **kwargs)
  • 处理密码的方法:
    • 设置密码: set_password(raw_password)
    • 校验密码: check_password(raw_password)

1.2 自定义用户模型类

思考:为什么要自定义用户模型类??

  • 如今几乎所有的web应用都需要用户提供手机号码,单默认的用户模型类中没有mobile字段
  • 随着业务的发展,未来很可能需要自定义用户模型
  • django强烈推荐在开始一个项目时设置一个自定义的用户模型

如何自定义模型类??

  • 继承自AbstractUser(最简单可行的方法,详情见官方文档)
  • 新增 mobile 字段

在 users.models.py 模块中定义模型如下:

import re

from django.db import models

from django.contrib.auth.models import AbstractUser

from django.core.exceptions import ValidationError

def validate_mobile(value):
    if not re.match(r'1[3-9]\d{9}', value):
        raise ValidationError('手机号码格式不正确')

class User(AbstractUser):
    """
   Custom user model.
   Add mobile field to Django user model
   """

    mobile = models.CharField(
        '手机号码', max_length=11, unique=True, help_text='手机号码', null=True, blank=T

        error_messages={'unique': '手机号码已注册'}, validators=[validate_mobile])

     REQUIRED_FIELDS = ['mobile']  # 在通过 createsuperuser 管理命令创建用户时,将提示输入

mobile字段
    
    def __str__(self):
        return self.username

    class Meta:
        db_table = 'tb_user'  # 表名

        verbose_name = 'user'  # 站点显示名

        verbose_name_plural = 'users'  # 复数显示

   

1.3 知识要点:

1. Django自带用户认证系统,核心就是User对象,并封装了一系列可用的方法和属性。 

2. Django用户认证系统包含了一系列对用户的操作,比如:模型类,认证,权限,分组,密码处理等。 

3. Django用户认证系统中的用户模型类可以自定义,最简单的方法是继承自AbstractUser。 

4. 更多Django中的自定义验证见官方文档

二、迁移用户模型类

2.1 指定用户模型类

Django是通过配置项 AUTH_USER_MODEL 来确定项目中到底使用哪个用户模型,所以我们需要修改配置指定我们的自 定义的用户模型。

配置规则:

# AUTH_USER_MODEL = '应用名.模型类名'

# 指定本项目用户模型类 settings.py 设置,【应用名.模型名】
AUTH_USER_MODEL = 'users.User'

2.2 迁移用户模型类

python manage.py makemigrations

python manage.py migrate

2.3 知识要点

1. 用 户 认 证 系 统 中 所用的 用 户 模 型 类 , 是 通 过 全 局 配 置 项  AUTH_USER_MODEL决 定 的 。 

2. 如 果 迁 移 自 定 义 用 户 模 型 类 , 必 须 先 配 置  AUTH_USER_MODEL 。 

3. 注 意 在 迁 移 之 前 , 运 行 服 务 会 报 错 , 因 为 默 认 项 目 依 赖 用 户 模 型

2.4 创建一个超级管理员

使用一下命令:

python .\manage.py createsuperuser

1690701666403-330e69e0-1f0c-4e54-8ea5-5ae49c51c57c.png

三、用户认证

身份验证是将传入请求与一组标识凭据(例如请求来自的用户或用于签名的令牌)相关联的机制。然后,权限限制 策略可以使用这些凭据来确定是否应该允许请求。

3.1 安装RESTframwork

安装:

pip install djangorestframework

注册:

在配置 INSTALLED_APPS 中添加 restframework

INSTALLED_APPS = [
    ...
    'rest_framework'
]

3.2 用户认证方案

REST framework 提供了许多开箱即用的身份验证方案,还允许您实现自定义方案

3.2.1 BasicAuthentication

此身份验证方案使用HTTP 基本身份验证,根据用户的用户名和密码进行签名。基本身份验证通常仅适用于测 试。 

3.2.2 TokenAuthentication

此身份验证方案使用简单的、基于令牌的 HTTP 身份验证方案。令牌身份验证适用于客户端-服务器设置,例如,本机桌面和移动客户端。 

要使用 TokenAuthentication 方案,您需要配置身份验证类以包含 TokenAuthentication ,并另外包含 rest_framework.authtoken 在您的 INSTALLED_APPS 设置中:

INSTALLED_APPS = [
   ...
    'rest_framework.authtoken'
]

因为token保存在数据中,所以还需要数据库迁移。

3.2.3 SessionAuthentication

此身份验证方案使用 Django 的默认会话后端进行身份验证。会话身份验证适用于在与您的网站相同的会话上 下文中运行的 AJAX 客户端。

特点: 

  • 保持在服务端, 增加服务器开销 
  • 分布式架构中, 难以维持Session会话同步 
  • CSRF攻击风险

3.2.4 JSON Web Token认证

JSON Web Token 是一个相当新的标准,可用于基于令牌的身份验证。与内置TokenAuthentication 方案不 同,JWT Authentication 不需要使用数据库来验证令牌。

jwt原理:

JSON Web Token (缩写JWT)是目前最流行的跨域认证解决方案。 

jwt的原理是,服务器认证以后,生成一个JSON对象,发回给用户,就像下面这样。

{
  "姓名": "心蓝",
  "角色": "管理员",
  "到期时间": "2020年10月1日0点0分"

}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户 篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。 服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

JWT的数据结构

实际的 JWT 大概就像下面这样。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VybmFtZSI6InB5MzQiLCJleHAiOiIxNjAxNDU4ODI2LjM5MjU5NyJ9.
e1c994e615cfbf3a81a13076b7d05c98a752bbd9381f551ad568ef287d439980

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示, 将它写成了几行。 

JWT 的三个部分依次如下。 

  • Header(头部) 

是可以解密的,这个相当于一个算法协议,告诉服务器这个串是怎么加密的

  • Payload(负载)

是可以解密的,解密之后,类似于以下这种效果:

{

"姓名": "心蓝",

"角色": "管理员",

"到期时间": "2020年10月1日0点0分"

}

  • Signature(签名)

不能被解密

注意:

认证原理:服务器会根据JWT提供的头、负载,然后进行特殊的算法,生成一个签名数据,让签名(请求中带的)与签名(新生成的)对比,如果正确则认证成功

JWT的使用方式:

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域, 所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

Authorization: Bearer 

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

特点: 

  • 保存在客户端 跨语言、跨平台
  • 拓展性强 
  • 鉴权性能高 

本项目使用此种验证 

3.3 设置认证方案

3.3.1 安装JWT插件

RESTframework没有实现jwt验证,第三方包djangorestframework-simplejwt 提供了可拔插的jwt验证功能。 

使用pip进行安装:

pip install djangorestframework-simplejwt

并在 INSTALLED_APPS 中注册 

INSTALLED_APPS = [
 ...
 'rest_framework_simplejwt',
 ...
]

3.3.2 配置认证的类

RESTframework使用配置 DEFAULT_AUTHENTICATION_CLASSES 来设置默认的全局用户验证方案。在项目配置 中添加如下配置: 

REST_FRAMEWORK = {
 'DEFAULT_AUTHENTICATION_CLASSES': [
     'rest_framework_simplejwt.authentication.JWTAuthentication',   #

     'rest_framework.authentication.SessionAuthentication',	# session鉴权
 ]
}

REST framework 将尝试对列表中的每个类进行身份验证,并将设置 request.user 和 request.auth 使用成 功身份验证的第一个类的返回值。 如果没有类进行身份验证, request.user 则将设置为的实例 

django.contrib.auth.models.AnonymousUser ,并将 request.auth 设置为 None 。 上面的配置表示先进行jwt验证,如果不成功就是使用session验证。

问题一:为什么要设置session鉴权??

因为以这种方式进行登录时,需要session鉴权,而且也需要在根路由中设置

1695455626980-9a8bdb53-2c24-45b8-a517-12684c042bc2.png

1695455696605-462c8e76-b6fa-471a-b0b1-6e86f0457682.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值