1005.Django项目用户功能之认证权限以及班级管理

Posted lxinghua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1005.Django项目用户功能之认证权限以及班级管理相关的知识,希望对你有一定的参考价值。

一、Token

1. Token概述

在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请,登录系统使用Token、令牌、代表执行某些操作的权利的对象。更通俗点可以叫暗号,在一些数据传输之前,要先对暗号的核对,不同的暗号被授权不同的数据操作。

方法:①引入--客户端请求数据,服务端频繁的去数据库匹配用户是否正确,重复资源消耗;②定义--服务端生成的一串字符串,以作客户端进行请求的一个令牌;③目的:减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

基于JWT的Token认证:

①header--头部数据包含使用的加密算法;②playload--Token要包含的数据,内容可以自定义,也可以参考标准字段,lss、sub、exp、iat;③ signature--签名,将header和playload使用base64编码生成再加入签名字符使用,加密算法加密得到唯一的签名,防止其他人来篡改token中的信息。

2. 登录与认证流程

①请求:用户发起请求,传入用户名和密码;

②验证:服务器静心更严重用户的信息;

③通过验证返回token令牌,客户端存储token,不通过返回错误信息提示登录失败;

④认证:每次请求都携带token服务器验证token,正确才返回数据。

3. Django-rest-framework-jwt

参考:https://jpadilla.github.io/django-rest-framework-jwt/

① 安装django-rest-framework-jwt   虚拟环境中  pip install djangorestframework-jwt -i https://pypi.douban.com/simple

② settings.py文件中导入以下代码

REST_FRAMEWORK = 
    \'DEFAULT_PERMISSION_CLASSES\': (
        \'rest_framework.permissions.IsAuthenticated\',
    ),
    \'DEFAULT_AUTHENTICATION_CLASSES\': (
        \'rest_framework_jwt.authentication.JSONWebTokenAuthentication\',
        \'rest_framework.authentication.SessionAuthentication\',
        \'rest_framework.authentication.BasicAuthentication\',
    ),

新建app users,并进行app添加,以及需要配置app urls路由以及项目urls等信息。

开启程序前端访问:

暂时无users用户,怎么创建users?   因占时未编写注册功能,所以需要创建users可以采用以下方式:

Tools>RUN manage.py Task.. 进入界面后 输入createsupperuser 即可开始创建user,此方法创建的user为超级管理员用户。

(密码随意!)

然后访问admin,进入登录界面,输入账号密码即可进入。

进入后即可进行用户创建以及权限设置!

可进行user的添加分组

再次访问用户登录界面,进行用户登录后即可看到对应的token加密令牌!

二、班级管理

1. 模型

首先在models.py中存在大量的模型类需要建立,每个模型都有数据项目需要建立,其中如create_time、update_time、is_delete等都是相同的项目,如何整合了?可以在项目目录下新建utils文件,创建modelsMixin.py文件进行App的models.py文件中模型类相同的项目进行整合处理。

完成以上模型类相同项目整合后,在app的models.py文件可直接打入整合模型,以供app models.py建立模型类后可进行继承!若出现不需要的项目则可选择需要的模型类进行继承

app school中models.py文件建立班级模型类,继承整合模型类即可实现共同项目的创建更新等

字段名 类型 长度 NULL 备注
Name Char 30 False 班级名
Slogan Text   True 口号
create_time Datetime   False 创建时间
update_time Datetime   False 更新时间
is_delete Boolean   False 逻辑删除,默认为False
Member ManyToMany   False 班级成员、外键

 

2. 序列化器

完成上述models模型类建立后,进行映射模型类,过滤is_delete字段,并隐藏逻辑删除字段等序列化作业

 

3. 视图

创建视图,返回数据!

4. 路由

创建路由器,注册路由,拼接路由器。

三、权限

四、SerializerMethodField

美多商城项目 02用户注册

一、用户模型类

1.1 定义用户模型类

1. Django默认用户认证系统

  • Django自带用户认证系统
    • 它处理用户账号、组、权限以及基于cookie的用户会话。
  • Django认证系统位置
    • django.contrib.auth包含认证框架的核心和默认的模型。
    • django.contrib.contenttypes是Django内容类型系统,它允许权限与你创建的模型关联。
  • Django认证系统同时处理认证和授权
    • 认证:验证一个用户是否它声称的那个人,可用于账号登录。
    • 授权:授权决定一个通过了认证的用户被允许做什么。
  • Django认证系统包含的内容
    • 用户:用户模型类、用户认证。
    • 权限:标识一个用户是否可以做一个特定的任务,MIS系统常用到。
    • 组:对多个具有相同权限的用户进行统一管理,MIS系统常用到。
    • 密码:一个可配置的密码哈希系统,设置密码、密码校验。

2. Django默认用户模型类

  • Django认证系统中提供了用户模型类User保存用户的数据。
    • User对象是认证系统的核心。
  • Django认证系统用户模型类位置

    • django.contrib.auth.models.User

  • 父类AbstractUser介绍

    • User对象基本属性
      • 创建用户必选:username、password
      • 创建用户可选:email、first_name、last_name、last_login、date_joined、is_active 、is_staff、is_superuse
      • 判断用户是否通过认证: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)

3. 自定义用户模型类

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

  • 观察注册界面会发现,美多商城注册数据必选用户mobile信息
  • 但是Django默认用户模型类中没有mobile字段,所以要自定义用户模型类。

如何自定义用户模型类?

  • 继承自AbstractUser(可通过阅读Django默认用户模型类的源码得知) 。
  • 新增mobile字段。
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.


class User(AbstractUser):
    """自定义用户模型类"""
    mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')

    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

4. 知识要点

  1. Django自带用户认证系统核心就是User对象
  2. Django用户认证系统包含了一系列对用户的操作,比如:模型类,认证,权限,分组,密码处理等。
  3. Django用户认证系统中的用户模型类可以自定义,继承自AbstractUser
  4. Django用户认证系统说明文档

1.2 迁移用户模型类

1. 指定用户模型类

文档

思考:为什么Django默认用户模型类是User?

  • 阅读源代码:'django.conf.global_settings’
    AUTH_USER_MODEL = 'auth.User'
    

结论:

  • Django用户模型类是通过全局配置项AUTH_USER_MODEL决定的

配置规则:

AUTH_USER_MODEL = '应用名.模型类名'
# 指定本项目用户模型类
AUTH_USER_MODEL = 'users.User'

2. 迁移用户模型类

1.创建迁移文件

  • python manage.py makemigrations

 

2.执行迁移文件

  • python manage.py migrate

 

3. 知识要点

  1. 用户认证系统中的用户模型类,是通过全局配置项AUTH_USER_MODEL决定的。
  2. 如果迁移自定义用户模型类,必须先配置 AUTH_USER_MODEL

二、用户注册业务实现

2.1 RESTful 设计方法( 入门 )

为什么需要使用 RESTful

在前后端分离的应用模式里,后端 API 接口如何定义?

例如

行业中以前的定义方式:

1 增加商品

# 增加商品
POST  /add-goods/

前端发送了 post 请求

请求路径为: /add-goods/

2 删除商品

# 删除商品
POST  /delete-goods/

前端又发送了 post 请求

请求路径为: /delete-goods/

3 修改商品

# 修改商品
POST /update-goods/ 修改商品

前端还是发送的 post 请求

请求路径为: /update-goods/

4 查询商品

# 查询商品
GET /get-goods/ 查询商品

前端发送的 get 请求

请求路径为: /get-goods/

总结:

对于接口的请求方式与路径,每个后端开发人员可能都有自己的定义方式,风格迥异。

是否存在一种统一的定义方式,被广大开发人员接受认可的方式呢?

这就是被普遍采用的 API 的 RESTful 设计风格.

路径

url 补充说明:

 

只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应.

GET   /products/4 :前端获取后端的单个产品(4号商品)
GET   /products :  前端获取后端的所有产品

POST  /products :  前端发给后端数据保存到后端
PUT   /products/4 :前端修改后端保存的数据
DELETE /products/4 : 前端删除后端保存的4号数据

名词能够使结构简洁.

API 中的名词应该使用复数.

举例来说,获取产品的 API 可以这样定义

获取单个产品:

http:
//127.0.0.1:8080/AppName/rest/products/1
获取所有产品: 

http:
//127.0.0.1:8080/AppName/rest/products

HTTP 动词

常用的HTTP动词有下面四个(括号里是对应的 SQL 命令).

- GET :    取出服务器资源 (一项或多项)
- POST :   往服务器新增一个资源.
- PUT :    修改服务器存储的资源 (客户端需提供修改所需的完整资源)
- DELETE :  删除服务器资源

下面是一些例子:

GET /zoos: 取出所有动物园
POST /zoos:新建一个动物园(上传文件)
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:取出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

2.2 用户名重复注册

1. 用户名重复注册逻辑分析

2. 用户名重复注册接口设计和定义

1.请求方式

选项方案
请求方法GET
请求地址/usernames/(?P<username>[a-zA-Z0-9_-]5,20)/count/

2.请求参数:路径参数

参数名类型是否必传说明
usernamestring用户名

3.响应结果:JSON

响应结果响应内容
code状态码
errmsg错误信息
count记录该用户名的个数

3. 用户名重复注册后端逻辑

from django.views import View
from apps.users.models import User
from django.http import JsonResponse

class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        """
        :param request: 请求对象
        :param username: 用户名
        :return: JSON
        """
        count = User.objects.filter(username=username).count()
        return JsonResponse('code': 0, 'errmsg': 'OK', 'count': count)

4.添加路由转换器

在utils包下创建一个converters.py文件

class UsernameConverter:
    """自定义路由转换器去匹配用户名"""
    # 定义匹配用户名的正则表达式
    regex = '[a-zA-Z0-9_-]5,20'

    def to_python(self, value):
        return str(value)

在总路由中添加路由转换器

from django.contrib import admin
from django.urls import path,include

from utils.converters import UsernameConverter
from django.urls import register_converter

register_converter(UsernameConverter,'username')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('apps.users.urls'))
]

在子应用中调用验证

from django.urls import path
from . import views

urlpatterns = [
    # 判断用户名是否重复
    path('usernames/<username:username>/count/',views.UsernameCountView.as_view()),
]

 2.3 跨域CORS

我们的前端和后端分别是两个不同的端口

位置域名
前端服务www.meiduo.site:8080
后端服务www.meiduo.site:8000

现在,前端与后端分处不同的域名,这就涉及到跨域访问数据的问题,因为浏览器的同源策略,默认是不支持两个不同域间相互访问数据,而我们需要在两个域名间相互传递数据,这时我们就要为后端添加跨域访问的支持。

我们使用CORS来解决后端对跨域访问的支持。

使用django-cors-headers扩展

参考文档https://github.com/ottoyiu/django-cors-headers/

安装

pip install django-cors-headers

添加应用

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

中间层设置

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

添加白名单

# CORS
CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1:8080',
    'http://localhost:8080',
    'http://www.meiduo.site:8080',
    'http://www.meiduo.site:8000'
)
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie
  • 凡是出现在白名单中的域名,都可以访问后端接口
  • CORS_ALLOW_CREDENTIALS 指明在跨域访问中,后端是否支持对cookie的操作。

2.4 手机号重复注册(作业)

1. 手机号重复注册逻辑分析

2. 手机号重复注册接口设计和定义

1.请求方式

选项方案
请求方法GET
请求地址/mobiles/(?P<mobile>1[3-9]\\d9)/count/

2.请求参数:路径参数

参数名类型是否必传说明
mobilestring手机号

3.响应结果:JSON

响应结果响应内容
code状态码
errmsg错误信息
count记录该用户名的个数

3. 手机号重复注册后端逻辑

class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        """
        :param request: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse('code': 0, 'errmsg': 'OK', 'count': count)

4.添加路由转换器

在utils包下的converters.py文件添加转换器

class MobileConverter:
    """自定义路由转换器去匹配手机号"""
    # 定义匹配手机号的正则表达式
    regex = '1[3-9]\\d9'

    def to_python(self, value):
        # to_python:将匹配结果传递到视图内部时使用
        return str(value)

在总路由中添加路由转换器

from django.contrib import admin
from django.urls import path,include

from utils.converters import UsernameConverter
from django.urls import register_converter

register_converter(UsernameConverter,'username')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('apps.users.urls'))
]

在子应用中调用验证

from django.urls import path
from . import views

urlpatterns = [
    # 判断用户名是否重复
    path('usernames/<username:username>/count/',views.UsernameCountView.as_view()),
]

 2.5 用户注册业务逻辑分析

1. 用户注册业务逻辑分析

2.6 用户注册接口设计和定义

1. 用户注册接口设计

1.请求方式

选项方案
请求方法POST
请求地址/register/

2.请求参数:JSON

参数名类型是否必传说明
usernamestring用户名
passwordstring密码
password2string确认密码
mobilestring手机号
sms_codestring短信验证码
allowstring是否同意用户协议

3.响应结果:JSON

响应结果响应内容
code响应码 0 表示成功 400表示失败
errmsg返回信息

2. 用户注册接口定义

1.注册视图

class RegisterView(View):
    """用户注册"""

    def post(self, request):
        """
        实现用户注册
        :param request: 请求对象
        :return: 注册结果
        """
        pass

2.总路由

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('apps.users.urls')),
]

3.子路由

urlpatterns = [
    # 注册
    path('register/', views.RegisterView.as_view()),
]

 2.7 用户注册后端逻辑

1. 接收参数

  import json
  # 1.接收参数:请求体中的JSON数据 request.body
  json_bytes = request.body  # 从请求体中获取原始的JSON数据,bytes类型的
  json_str = json_bytes.decode()  # 将bytes类型的JSON数据,转成JSON字符串
  json_dict = json.loads(json_str)  # 将JSON字符串,转成python的标准字典
  # json_dict = json.loads(request.body.decode())

  # 提取参数
  username = json_dict.get('username')
  password = json_dict.get('password')
  password2 = json_dict.get('password2')
  mobile = json_dict.get('mobile')
  allow = json_dict.get('allow')
  sms_code = json_dict.get('sms_code')

2. 校验参数

from django import http
import re

# 判断参数是否齐全
if not all([username, password, password2, mobile, allow]):
    return http.JsonResponse('code':400, 'errmsg':'缺少必传参数!')
# 判断用户名是否是5-20个字符
if not re.match(r'^[a-zA-Z0-9_]5,20$', username):
    return http.JsonResponse('code': 400, 'errmsg': 'username格式有误!')
# 判断密码是否是8-20个数字
if not re.match(r'^[0-9A-Za-z]8,20$', password):
    return http.JsonResponse('code': 400, 'errmsg': 'password格式有误!')
# 判断两次密码是否一致
if password != password2:
    return http.JsonResponse('code': 400, 'errmsg': '两次输入不对!')
# 判断手机号是否合法
if not re.match(r'^1[3-9]\\d9$', mobile):
    return http.JsonResponse('code': 400, 'errmsg': 'mobile格式有误!')
# 判断是否勾选用户协议
if allow != True:
    return http.JsonResponse('code': 400, 'errmsg': 'allow格式有误!')

这里校验的参数,前端已经校验过,如果此时参数还是出错,说明该请求是非正常渠道发送的,所以直接禁止掉。

3. 保存注册数据,返回相应

 try:
    user = User.objects.create_user(username=username,
                                    password=password,
                                    mobile=mobile)
except Exception as e:
    return http.JsonResponse('code': 400, 'errmsg': '注册失败!')


return http.JsonResponse('code': 0, 'errmsg': '注册成功!')
  • 这里使用Django认证系统用户模型类提供的create_user()方法创建新的用户。
  • 这里create_user()方法中封装了set_password()方法加密密码。

注意

我们通过postman或者浏览器验证的时候回出现CSRF Forbidden问题

 

解决CSRF Forbidden问题, 关闭csrf中间件

2.8 状态保持

说明:

  • 如果需求是注册成功后即表示用户认证通过,那么此时可以在注册成功后实现状态保持
  • 如果需求是注册成功后不表示用户认证通过,那么此时不用在注册成功后实现状态保持

美多商城的需求是:注册成功后即表示用户认证通过

1. login()方法介绍

  1. 状态保持:
    • 将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前session会话中
  2. login()方法:
    • Django用户认证系统提供了 login() 方法
    • 封装了写入session的操作,帮助我们快速实现状态保持
  3. login()位置:

    • django.contrib.auth.__init__.py文件中

      login(request, user)
      

2. login()方法使用

# 保存注册数据
try:
    user = User.objects.create_user(username=username, password=password, mobile=mobile)
except DatabaseError:
    return http.JsonResponse('code': 400, 'errmsg': '注册失败!')

# 实现状态保持
login(request, user)

# 响应注册结果
return http.JsonResponse('code': 0, 'errmsg': '注册成功!')

3. 查看状态保持结果

 

以上是关于1005.Django项目用户功能之认证权限以及班级管理的主要内容,如果未能解决你的问题,请参考以下文章

#私藏项目实操分享# Spring专题「开发实战」Spring Security与JWT实现权限管控以及登录认证指南

#私藏项目实操分享#愚公系列2022年05月 Python教学课程 72-DRF框架之认证和权限

BOS项目 第7天(shiro权限框架进行认证和授权)

Django之用户认证功能

spring项目篇5----shiro以及实现登陆认证

SharePoint服务器端对象模型 之 访问用户用户组和权限(Part 1)