drf jwt认证组件

常用的前后台分类认证 - jwt(json web token)

一、jwt认证规则

  • 全称:json web token
  • 解释:加密字符串的原始数据是json,后台产生,通过web传输给前台存储
  • 格式:三段式
    • 头(Header)、载荷(Payload)、签名(Signature)、
    • 头和载荷采用的是base64可逆加密,签名才有md5不可逆加密
  • 内容:
    • 头(基础信息,也可以为空):加密方式、公司信息、项目组信息、...
    • 载荷(核心信息):用户信息、过期时间、...
    • 签名(安全保障):头加密结果+载荷加密结果+服务器秘钥 的md5加密结果
  • 认证规则:
    • 后台一定要保障 服务器秘钥 的安全性(它是jwt的唯一安全保障)
    • 后台签发token -> 前台存储 -> 发送需要认证的请求带着token -> 后台校验得到合法的用户

1.1 为什么要有jwt认证

1) 后台不需要存储token,只需要存储签发与校验token的算法,效率远远大于后台存储和取出token完成校验
2) jwt算法认证,更适合服务器集群部署

二、jwt模块

  • 安装:pip install djangorestframework-jwt

  • 模块包名:rest_framework_jwt

三、jwt模块使用

  • 有了drf-jwt框架后,后期任务只需要重写登录即可:
    • 为什么要重写登录:drf-jwt只完成了账号密码登录,我们还需要手机登录,邮箱登录
    • 为什么不需要重写认证类:因为认证规则已经完成且固定不变,变得只有认证字符串的前缀,前缀可以在配置文件中配置

使用提供好的 jwt视图类三个接口:

  • 签发token接口、校验token、刷新token

    注:jwt视图类签发token的接口会帮你完成登陆并签发token,但drf-jwt只完成了账号密码登录,我们还需要手机登录,邮箱登录,就需要去重写jwt序列化类签发token实现多方式登录

    '''urls.py'''
    # 使用JWT认证组件实现好的视图
    from rest_framework_jwt.views import ObtainJSONWebToken,obtain_jwt_token
    urlpatterns = [
        # 使用JWT认证组件实现好的视图类来实现登陆认证
        # url(r"jwt_login/$",ObtainJSONWebToken.as_view())
        # jwt提供的简写形式
        url(r"jwt_login/$",obtain_jwt_token),
        url(r"jwt_refresh/$",refresh_jwt_token),
        url(r"jwt_verify/$",verify_jwt_token),
    ]
    

drf全局配置jwt认证组件

# drf的配置
REST_FRAMEWORK = {
    # 认证组件的全局配置
    'DEFAULT_AUTHENTICATION_CLASSES':[
        # jwt认证类
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ],
}

drf-jwt配置

# drf-jwt配置
import datetime
JWT_AUTH = {
    # token过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
    # 允许刷新
    # 'JWT_ALLOW_REFRESH': True,
    # # 刷新后的最大过期时间
    # 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
    # 认证前缀
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

重写jwt序列化类签发token实现多方式登录

'''serializers.py'''

# 导入JWT认证
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
import re
class LoginJWTModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField(write_only=True)
    password = serializers.CharField(write_only=True)

    class Meta:
        model = models.UserInfo
        fields = ('username', 'password')

    # 在全局钩子中签发token
    def validate(self, attrs):
        # user = authenticate(**attrs)
        # 账号密码登录 => 多方式登录
        user = self._many_method_login(**attrs)

        # 签发token,并将user和token存放到序列化对象中
        payload = jwt_payload_handler(user)     # 使用jwt认证模块,根据当前用户得到载荷
        token = jwt_encode_handler(payload)     # 使用jwt认证模块,得到token

        self.user = user
        self.token = token

        return attrs

    # 多方式登录
    def _many_method_login(self, **attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        if re.match(r'.*@.*', username):
            user = models.UserInfo.objects.filter(email=username).first()

        elif re.match(r'^1[3-9][0-9]{9}$', username):
            user = models.UserInfo.objects.filter(mobile=username).first()
        else:
            user = models.UserInfo.objects.filter(username=username).first()

        if not user:
            raise serializers.ValidationError({'username': '账号有误'})

        if not user.check_password(password):
            raise serializers.ValidationError({'password': '密码有误'})

        return user
'''views.py'''

'''
jwt 模块实现 签发token
重写jwt序列化类签发token实现多方式登录
'''
class JWTLoginAPIView(APIView):
    # 登陆 禁用认证和权限校验
    authentication_classes = []
    permission_classes = []
    def post(self, request, *args, **kwargs):
        ser_obj = serializers.LoginJWTModelSerializer(data=request.data)
        ser_obj.is_valid(raise_exception=True)
        return common.APIResponse(results={
            "username": ser_obj.user.username,
            "token" : ser_obj.token,
        })

四、前后台分离模式下信息交互规则

"""
1)任何人都能直接访问的接口:
	请求不管是get、还是post等,不需要做任何校验

2)必须登录后才能访问的接口:
	任何请求方式都可能做该方式的限制,请求必须在请求头中携带认证信息 - authorization
	
3)前台的认证信息获取只能通过登录接口:
	前台提供账号密码等信息,去后台换认证信息token
	
4)前台如何完成登录注销:
	前台登录成功一般在cookie中保存认证信息token,分离注销就是前台主动清除保存的token信息
"""
posted @ 2019-11-26 22:18  正在学习的Barry  阅读(231)  评论(0编辑  收藏  举报
-->