简单的方式生成认证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文件中配置
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表:
-
分析问题:
- 解决问题:
- 子应用内创建login.py
- 创建一个类继承于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)
- 创建一个视图,模仿源码
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
- 创建as_view()
admin_jwt_token = AdminJSONWebTokenView.as_view()
- 路由内修改为自定义函数