三大认证组件及jwt认证规则

三大认证组件及jwt认证规则

一、认证组件

一、认证规则

  1. 从请求头中(Authorization)获取认证信息(token)算法

  2. 若是没有拿到认证信息,直接断定该请求为匿名请求(游客) => 表明认证经过了,返回None数据库

  3. 若是拿到认证信息,进行信息校验,校验成功会获得请求对象(用户) => 表明认证经过了,认证方法返回元组(user, token)django

  4. 若是拿到的认证信息,进行信息校验,校验失败了,就抛出异常json

  5. 通常认证组件在settings中进行全局配置api

二、自定义认证类

咱们通常都不须要自定义认证类,在settings中全局配置第三方 jwt 认证组件提供的认证类便可,若是要自定义认证类步骤以下:安全

  1. 自定义认证类,首先继承 BaseAuthentication 类服务器

  2. 必须重写 authenticate(self, request) 方法cookie

    • 没有认证信息,返回None:匿名用户(游客) => 匿名用户request.user也有值,就是"匿名对象(Anonymous)"session

    • 有认证信息,且经过,返回(user, token):合法用户 => user对象会存到request.user中框架

    • 有认证信息,不经过,抛异常:非法用户

二、权限组件

一、权限规则

  1. 权限组件只有在认证经过后,再会执行,权限组件的目的就是判断认证经过的用户(匿名用户、有权限用户)

  2. 权限规则其实就是条件逻辑,有权限就返回True => 表明权限经过

  3. 条件逻辑判断失败,表明用户没有权限,返回False => 权限失败

  4. 权限组件通知在视图类中局部配置

二、自定义权限类

咱们通常在视图类中局部配置drf提供的权限类,可是也会自定义权限类完成局部配置

  1. 自定义权限类,首先继承 BasePermission 类

  2. 必须重写 has_permission(self, request, view): 方法

    • 设置权限条件,条件经过,返回True => 有权限

    • 设置权限条件,条件不经过,返回False => 没有权限

  3. drf提供的权限类:

    • AllowAny:匿名与合法用户均可以

    • IsAuthenticated:必须登陆,只有合法用户能够

    • IsAdminUser:必须是admin后台用户

    • IsAuthenticatedOrReadOnly:匿名只读,合法用户无限制

from rest_framework.permissions import AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly
class UserCenterViewSet(GenericViewSet, mixins.RetrieveModelMixin):
    permission_classes = [IsAuthenticated, ]
​
    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializers.UserCenterSerializer

三、jwt认证示意图

一、jwt优势:

  1. 没有数据库写操做 => 高效

  1. 服务器不存在token => 低耗

  1. 签发校验都是算法 => 集群

二、基于session的认证(通常不使用)

三、基于session认证下的集群部署

四、基于jwt的认证

五、基于jwt认证下的服务器集群

四、jwt认证算法:签发与校验

一、jwt分三段式:头.体.签名 (head.payload.sign)

二、头和体是可逆加密,让服务器能够反解出user对象;签名是不可逆加密,保证整个token的安全性

三、头.体.签名三部分,都是采用json格式的字符串进行加密,可逆加密通常采用base64算法,不可逆加密通常采用hash(md5)算法

四、头中的内容是基本信息:公司信息、项目组信息、token采用的加密方式信息(通常不会变)

五、体中的内容是关键性信息:用户主键、用户名、签发是客户端信息(设备号、地址)、过时时间

六、签名中的内容是安全信息:头的加密结果+体的加密结果+服务器不对外公开的安全码,进行 md5 加密,{"head":"头的加密字符串","payload":"体的加密字符串","secret_key": "安全码"}

一、签发:根据登陆请求提交的帐号+密码+设备信息 签发token

  1. 用基本信息存储json字典,采用base64算法加密获得 头字符串

  2. 用关键信息存储json字典,采用base64算法加密获得 体字符串

  3. 用头加密字符串+体加密字符串+安全码信息存储json字典,采用hash md5算法加密获得 签名字符串

帐户密码就能根据User表获得user对象,造成的三段字符串用 . 拼接成token返回给前台

二、校验:根据客户端带token的请求 反解出 user 对象

  1. 将token按 . 拆分为三段字符串,第一段:头加密字符串,通常不须要作任何处理

  2. 第二段:体加密字符串,要反解出用户主键,经过主键从User表中就能获得登陆用户,过时时间和设备信息都是安全信息,确保token没过时,且同一个设备来的

  3. 再用 第一段+第二段+服务器安全码 不可逆md5加密,与第三段签名字符串进行对比校验,经过后才能表明第二段校验的user对象是合法用户

五、drf项目的jwt认证开发流程

  1. 用帐号密码访问登陆接口,登陆接口逻辑中调用 签发token算法,获得token,返回给客户端,客户端本身存到cookies中

  2. 校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,全部视图类请求,都会进行认证校验,因此请求带了token,就会反解出user对象,在视图类中用request.user就能访问登陆的用户

注:登陆接口须要作认证+权限两个局部禁用

六、drf-jwt框架基本使用

一、安装

pip install djangorestframework-jwt

二、签发token(登陆接口):视图类已经写好,配置一下路由就行(urls.py)

# api/urls.py
urlpatterns = [
     ...
    url('^login/$', ObtainJSONWebToken.as_view()),
]
​
# Postman请求:/api/login/,提供username和password便可

三、校验token(认证组件):认证类已经写好了,全局配置一下认证组件就好了(settings.py)

# drf-jwt的配置
import datetime
JWT_AUTH = {
    # 配置过时时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
​
​
# drf配置(把配置放在最下方)
REST_FRAMEWORK = {
    # 自定义三大认证配置类们
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_jwt.authentication.JSONWebTokenAuthentication'],
    # 'DEFAULT_PERMISSION_CLASSES': [],
    # 'DEFAULT_THROTTLE_CLASSES': [],
}

四、设置须要登陆才能访问的接口进行测试(views.py)

from rest_framework.permissions import IsAuthenticated
class UserCenterViewSet(GenericViewSet, mixins.RetrieveModelMixin):
    # 设置必须登陆才能访问的权限类
    permission_classes = [IsAuthenticated, ]
​
    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializers.UserCenterSerializer

测试:

1)用 {"username": "你的用户", "password": "你的密码"} 访问 post请求 /api/login/ 接口拿到 token 字符串

2)在请求头用 Authorization 携带 "jwt 登陆获得的token" 访问 get请求 /api/user/center/1/ 接口访问我的中心