小火车 2019-12-31
目录
SimpleRouter
,但该类只包含了视图家族中的6大接口,其余群增,群整体改,群局部改,群删4大接口没有对应的路由。所以需要我们手动自定义路由组件from rest_framework.routers import Route, DynamicRoute, SimpleRouter as DRFSimpleRouter class SimpleRouter(DRFSimpleRouter): routes = [ # List route. /资源s/ Route( url=r'^{prefix}{trailing_slash}$', mapping={ 'get': 'list', # 群查 'post': 'create', # 单增、群增 'put': 'multiple_update', # 群整改 'patch': 'multiple_partial_update', # 群局改 'delete': 'multiple_destroy', # 群删 }, name='{basename}-list', detail=False, initkwargs={'suffix': 'List'} ), # Dynamically generated list routes. Generated using # @action(detail=False) decorator on methods of the viewset. DynamicRoute( url=r'^{prefix}/{url_path}{trailing_slash}$', name='{basename}-{url_name}', detail=False, initkwargs={} ), # Detail route. /资源s/(pk)/ Route( url=r'^{prefix}/{lookup}{trailing_slash}$', mapping={ 'get': 'retrieve', # 单查 'put': 'update', # 单整改 'patch': 'partial_update', # 单局改 'delete': 'destroy' # 单删 }, name='{basename}-detail', detail=True, initkwargs={'suffix': 'Instance'} ), # Dynamically generated detail routes. Generated using # @action(detail=True) decorator on methods of the viewset. DynamicRoute( url=r'^{prefix}/{lookup}/{url_path}{trailing_slash}$', name='{basename}-{url_name}', detail=True, initkwargs={} ), ] # 对外提供router对象 router = SimpleRouter() # eg: router.register('users', UserModelViewSet, basename='user')
在Django自带的后天管理系统中,通过Django的auth模块创建的用户表对应的页面,展示的信息都可以由自己配置。
实例
# admin文件中: from django.contrib import admin from . import models from django.contrib.auth.admin import UserAdmin as AuthUserAdmin # 重写UserAdmin类 class UserAdmin(AuthUserAdmin): # 添加用户页面可控制字段 add_fieldsets = ( (None, { 'classes': ('wide',), # 自定义添加用户页面中的可控制字段,可以让密码变成密文 'fields': ('username', 'password1', 'password2', 'is_staff', 'mobile'), }), ) # 自定义用户信息展示页面显示的字段 list_display = ('username', 'email', 'mobile', 'is_staff') # 注册自定义User表,用admin管理,配置UserAdmin,定制化管理页面 admin.site.register(models.User, UserAdmin) # models文件中: # 重点:通过继承AbstractUser创建的用户管理表,一定要在第一次数据库迁移时完成 from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile = models.CharField(max_length=11, verbose_name='电话号码', unique=True) # 配置User类 class Meta: # 控制数据表创建时的表名直接就是 my_user,没有前缀 db_table = 'my_user' # 使用admin后台管理是时显示User表时变为”用户表“(就是汉化) verbose_name_plural = '用户表' def __str__(self): return self.username
就是身份认证,校验用户:游客、合法用户、非法用户
1. 游客:代表校验通过,直接进入下一步校验(权限校验) 2. 合法用户:代表校验通过,将用户存储在request.user中,再进入下一步校验(权限校验) 3. 非法用户:代表校验失败,抛出异常,返回403权限异常结果 4. 只要通过认证不管是游客还是登录用户,request.user都有值
校验用户权限:必须是已登录的
1. 针对所有用户——》校验用户的读写权限 。如:游客只读,正规用户可读可写 2. 认证通过:可以进入下一步校验(频率认证) 3. 认证失败:抛出异常,返回403权限异常结果
限制视图接口在一定的时间内被访问的频率次数
没有达到限次:正常访问接口
达到限次:限制时间内不能访问,限制时间达到后,可以重新访问
```
一般项目中,采用的是传统的RBAC(Role-BasedAccessControl)。 传统的RBAC有两种:权限三表和权限五表(没有UP关系表) 权限三表:User、Group、Permission表 权限五表:User、Group、Permission、UG关系表、GP关系表
Django中Auth组件采用的是:权限六表(在传统RBAC基础上增加UP关系表) 权限六表: User、Group、Permission、UG关系表、UP关系表、GP关系表 ************************************************ 注意:用户管理表(即权限六表),一定要在第一次数据库迁移时完成 ************************************************
1)数据库不需要存储token,所以服务器的 IO 操作会减少(没有IO写操作) 2)客户端存Token,服务器只存储签发与校验算法,执行效率高 3)签发与校验算法在多个服务器上可以直接统一,所以jwt认证规则下,服务器做集群非常便捷(服务器集群的意思是可有有多个服务器,token的签发和校验可以再不同的服务器上进行)
头.载荷.签名
三部分组成,中间由 点 连接jwt的头部中一般是基本信息(内容也可以为空):公司名称、项目组信息、开发者信息等
jwt的载荷中一般是核心信息:用户主键、用户账号、客户端设备信息、token的过期时间等
jwt的签名中是安全信息:头的加密结果、载荷的加密结果、服务器的安全码(盐)...
1. 内容:头内容写死(可以为空{}):公司、项目组信息都是固定不变的 2. 算法:将需要的数据字典转化成json字符串,再将json字符串加密成base64字符串
1. 内容:用户账号、客户端设备信息是由客户端提供,用户主键是客户端提供账号密码校验User表通过后才能确定,过期时间根据当前时间与配置的过期时间相结合产生 2. 算法:将数据字典转化成json字符串,再将json字符串加密成base64字符串
1. 内容:先将头的加密结果,载荷的加密结果作为成员,再从服务器上拿安全码(不能让任何客户端知道),也可以额外包含载荷的部分(用户信息,设备信息) 2. 算法:将数据字典转化成json字符串,再将json字符串不可逆的加密成HS256字符串
将前三步产生的三个字符串用 . 连接产生三段式token
从客户端提交的请求中拿到token,用 . 分割成三段(如果不是三段,非法)
# 解密切分后的第一段,即头部 看情况做,一般不需要解密
# 解密切分的第二段,即载荷部分: 先用base64解密成json字符串,再转换成python格式的字典数据: i)用户主键与用户账号查询User表确定用户是否存在 ii)用本次请求提交的设备信息与解密后的载荷中的设备信息比对,确定前后是否是同一设备,决定是否对用户做安全提示(eg:短信邮箱提示异地登录)(同样的安全保障还可以为IP、登录地点等) iii)过期时间与当前时间比对,该token是否在有效时间内
# 用切分的第三段,即token中的签名部分进行校验 i)将用户最新提交的token中第一段和第二段字符串(即头、载荷加密字符串)和服务端的数据库安全码再组成字典,转换成json格式的字符串 ii)采用不可逆HS256加密对新组成的json字符串加密产生新的签名字符串 iii)新的签名字符串与第三段签名碰撞比对,一致才能确保token是合法的
前方算法都通过后,用载荷中的用户主键校验得到的User对象,就是该token代表的登录用户(Django项目一般都会把登录用户存放在request.user中)
刷新算法就是在签发完token后,在token的有效时间内,用户每次提交请求时都会刷新该token的有效时间。但每次刷新后的token有效时间都应该小于一个指定的时间。总而言之:就是说一个token应该有一个指定的有效时间,刷新时间后的有效时间要在该指定的有效时间之内变动,以此来加强token的安全性。
因此需要有一个算法来处理这个逻辑,这就是刷新算法
1)要在签发token的载荷中,额外添加两个时间信息:第一次签发token的时间,最多往后刷新的有效时间 2)每一请求携带token,不仅走校验算法验证token是否合法,还要额外请求刷新token的接口,完成token的刷新:校验规则与校验算法差不多,但是要将过期时间后移(没有超过有效时间,产生新token给客户端,如果超过了,刷新失败,token失效) 3)所以服务器不仅要配置过期时间,还需要配置最长刷新时间(即token最大有效时间)