DRF框架实战项目后台----登录视图和JSON Web Token认证

简单的方式生成认证token 登录管理员用户

  • 安装jwt(用于生成认证的token)
pip install djangorestframework-jwt
  • settings.py文件内添加drf框架认证配置
# drf 配置
REST_FRAMEWORK = {

    # 认证
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
  • 生成子应用meiduo_admin
cd apps
python ../manage.py startapp meiduo_admin
  • 添加urls.py,urls.py内写入内容
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('authorizations/', obtain_jwt_token),
]

from rest_framework_jwt.views import obtain_jwt_token导包
访问这个路由时去调用obtain_jwt_token这个函数,会自动去数据库查找用户名和密码是否正确,如果正确就会返回一个加密后的token


  • 测试登录成功

在这里插入图片描述


token生成的原理

查看源码:

  • ctrl点击进入源码在这里插入图片描述
    在这里插入图片描述

  • 发现继承黄色框内的这个类,点击进入在这里插入图片描述

  • 找到了post请求在这里插入图片描述

  • 查看序列化器在这里插入图片描述

  • 发现序列化器内验证了用户名和密码以及认证状态
    在这里插入图片描述


登录管理员只返回了Token的问题(自定义返回数据)

 管理员登录生成token的方法被封装了,都是自动生成的,
 这导致只返回了token一个参数,我们还需要返回用户名以及id

还需要返回用户名:
在这里插入图片描述

找出原因:

  • ctrl点击进入obtain_jwt_token查看源码
    在这里插入图片描述
    在这里插入图片描述
  • 终于在JSONWebTokenAPIView内找出了这个post请求,发现返回的response是黄色框内这个函数生成的
    在这里插入图片描述
  • 打断点,检查为什么只返回了token
    在这里插入图片描述
  • 进入方法发现
    在这里插入图片描述
    走到这里说明只要重写jwt_response_payload_handler这个方法就可以返回自定义的数据

解决问题:

  • 应用内创建utils.py文件

  • 重写返回数据的方法

def meiduo_jwt_response_payload_handler(token, user=None, request=None):
    return {
        'token': token,
        'username': user.username,
        'id': user.id
    }
  • 查看文档在settings.py文件中配置

Django REST framework JWT官方文档
在这里插入图片描述
在这里插入图片描述

JWT_AUTH = {
    # 设置token过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 设置使用自定义的response返回数据
    'JWT_RESPONSE_PAYLOAD_HANDLER':
        'apps.meiduo_admin.utils.meiduo_jwt_response_payload_handler',
}
  • 测试:
    在这里插入图片描述
    在这里插入图片描述

解决普通用户和管理员都能登录到后台的问题

  • Django自带的User表:
    在这里插入图片描述

  • 分析问题:

在这里插入图片描述

  • 解决问题:
  1. 子应用内创建login.py
    在这里插入图片描述
  2. 创建一个类继承于JSONWebTokenSerializer重写它的validate方法,只添加判断是否是管理员权限。
class AdminJSONWebTokenSerializer(JSONWebTokenSerializer):
    def validate(self, attrs):
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }

        if all(credentials.values()):
            user = authenticate(**credentials)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)
                    
                # 自定义只有管理员可以登录
                if not user.is_staff:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                payload = jwt_payload_handler(user)

                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)
  1. 创建一个视图,模仿源码
class AdminJSONWebTokenView(JSONWebTokenAPIView):
    """
    API View that receives a POST with a user's username and password.

    Returns a JSON Web Token that can be used for authenticated requests.
    """
    serializer_class = AdminJSONWebTokenSerializer

  1. 创建as_view()
admin_jwt_token = AdminJSONWebTokenView.as_view()
  1. 路由内修改为自定义函数
    在这里插入图片描述
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值