djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习
Django REST framework JWT
djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习
SECRET_KEY = '1)q(f8jrz^edwtr2#h8vj=$u)ip4fx7#h@c41gvxtgc!dj#wkc'
定期动态生成SECRET_KEY
字符串导包 https://blog.csdn.net/chaoguo1234/article/details/81277590
安装配置
安装
pip install djangorestframework-jwt
配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
Django REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法
from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
从api_settigs下去找,在rest_framework_jwt.settings下面
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
api_settings = APISettings(USER_SETTINGS, DEFAULTS, IMPORT_STRINGS) # 这三个参数分别对应settings文件下的参数
DEFAULTS 这个参数
DEFAULTS = {
...
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
...
}
从源码可以看出对应的就是
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER 中的 JWT_PAYLOAD_HANDLER ,key对应的value就是 'rest_framework_jwt.utils.jwt_payload_handler'
而rest_framework_jwt.utils.jwt_payload_handler其实就是一个导包路径
现在从这个路径下去寻找到utils下的jwt_payload_handler函数
def jwt_payload_handler(user):
username_field = get_username_field()
username = get_username(user) warnings.warn(
'The following fields will be removed in the future: '
'`email` and `user_id`. ',
DeprecationWarning
) payload = {
'user_id': user.pk,
'username': username,
'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA # JWT_EXPIRATION_DELTA对应的就是在我们配置里指定的过期时间
}
if hasattr(user, 'email'):
payload['email'] = user.email
if isinstance(user.pk, uuid.UUID):
payload['user_id'] = str(user.pk) payload[username_field] = username # Include original issued at time for a brand new token,
# to allow token refresh
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.utcnow().utctimetuple()
) if api_settings.JWT_AUDIENCE is not None:
payload['aud'] = api_settings.JWT_AUDIENCE if api_settings.JWT_ISSUER is not None:
payload['iss'] = api_settings.JWT_ISSUER return payload
下面在 jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER 用同样的方法找到JWT_ENCODE_HANDLER对应的value, 也就是导包路径
DEFAULTS = {
...
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
...
}
同样根据导包路径寻找
def jwt_encode_handler(payload):
key = api_settings.JWT_PRIVATE_KEY or jwt_get_secret_key(payload)
return jwt.encode(
payload,
key,
api_settings.JWT_ALGORITHM
).decode('utf-8')
生成token的过程

浏览器的保存策略

Django REST framework JWT提供了登录签发JWT的视图,可以直接使用
from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [
url(r'^authorizations/$', obtain_jwt_token),
]
但是默认的返回值仅有token,我们还需在返回值中增加username和user_id。
从 obtain_jwt_token 进去
路由: url(r'^authorizations/, obtain_jwt_token),
obtain_jwt_token来自$PYTHON_ENVTIONS_PATH/site-packages/rest_framework_jwt/views.py的102行和74-80行,代码如下
class ObtainJSONWebToken(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 = JSONWebTokenSerializer """
中间省略部分不相关代码
"""
obtain_jwt_token = ObtainJSONWebToken.as_view()
很明显:这个就是一个登录的视图集
查看下继承的JSONWebTokenAPIView视图
jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER ... class JSONWebTokenAPIView(APIView): # 继承至APIView
...
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) if serializer.is_valid():
user = serializer.object.get('user') or request.user
token = serializer.object.get('token')
response_data = jwt_response_payload_handler(token, user, request) # jwt_response_payload_handler 响应对象
response = Response(response_data)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
token,
expires=expiration,
httponly=True)
return response return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
在jwt_response_payload_handler 响应对象中找到
def jwt_response_payload_handler(token, user=None, request=None):
"""
Returns the response data for both the login and refresh views.
Override to return a custom response such as including the
serialized representation of the User. Example: def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': UserSerializer(user, context={'request': request}).data
} """
return {
'token': token
}
可以看出,登录后返回的响应对象仅仅有token一个key , 这对于大多数场景来说都是不合适的,所以需要来重写该方法
def jwt_response_payload_handler(token, user=None, request=None):
"""
自定义jwt认证成功返回数据
"""
return {
'token': token,
'user_id': user.id,
'username': user.username
}
因为我们自定义的该方法,所以也需要修改它的导包路径,之前也找到了它的导包路径传入的源码,则在配置文件中进行如下配置:
# JWT
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
}
这样,就实现了修改response响应对象
现在看完了继承的类视图,下面来看下序列化器:
在刚刚的源码中能看得到指定的序列化器就是 serializer_class = JSONWebTokenSerializer
既然指定了serializer_class = JSONWebTokenSerializer 说明是使用了DRF框架做验证, 那么验证用户登录时传输的参数的代码就是在序列化器类的代码中
序列化器类来自于$PYTHON_ENVTIONS_PATH/site-packages/rest_framework_jwt/serializers.py22-69行, 代码如下:
class JSONWebTokenSerializer(Serializer):
"""
省略部分代码
"""
def validate(self, attrs):
# 获取参数: 用户登录名称 + 密码
credentials = {
self.username_field: attrs.get(self.username_field),
'password': attrs.get('password')
} if all(credentials.values()):
# 用户登录时传入的参数完整, 则验证用户并获取用户对象
# 获取用户对象的代码在下面djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习的更多相关文章
- Django-REST-Framework JWT 实现SSO认证(上)
一.什么是Django-REST-Framework? Django-REST-framework 是基于Django框架的一个web RESTful风格开发的框架,它可以实现API接口的快速开发,但 ...
- Django-REST-Framework JWT 实现SSO认证(下)
在上一篇博客中,我已经对JSON Web 认证做了简单的解释,这篇博客是续篇,若不了解,请看上一篇博客:https://www.cnblogs.com/yushenglin/p/10863184.ht ...
- day77:luffy:导航栏的实现&DjangoRestFramework JWT&多条件登录
目录 1.导航栏的实现 2.登录前戏:用户表初始化 3.DjangoRestFramework JWT 4.多条件登录 5.登录状态的判断和退出登录 1.导航栏的实现 1.设计导航栏的model模型类 ...
- Django之自带的认证系统 auth模块
01-Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Dj ...
- spring jwt springboot RESTful API认证方式
RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authentication)和授权(Authorization)过程,保证API的安全性. Authenticatio ...
- SpringBoot系列 - 集成JWT实现接口权限认证
会飞的污熊 2018-01-22 16173 阅读 spring jwt springboot RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authenticati ...
- 基于JWT的token身份认证方案
一.使用JSON Web Token的好处? 1.性能问题. JWT方式将用户状态分散到了客户端中,相比于session,可以明显减轻服务端的内存压力. Session方式存储用户id的最大弊病在于S ...
- SpringBoot集成JWT 实现接口权限认证
JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的, 特别适用于分布式站点 ...
- .net core webapi jwt 更为清爽的认证
原文:.net core webapi jwt 更为清爽的认证 我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下 jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于 ...
随机推荐
- Spock - Document -04- Interaction Based Testing
Interaction Based Testing Peter Niederwieser, The Spock Framework TeamVersion 1.1 Interaction-based ...
- 2018.9.12 B树总结
1. B-Tree B-树是一种平衡的多路查找树,它在文件系统中很有用. 1.1 B-Tree 特性 关键字集合分布在整颗树中: 任何一个关键字出现且只出现在一个结点中: 搜索有可能在非叶子结点结束: ...
- javascript之网页跑马灯
---恢复内容开始--- <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- js判断页面在pc端打开还是移动端打开
js判断页面在pc端打开还是移动端打开,分别跳转不同的index.html window.addEventListener('load', function() { // true为手机,false为 ...
- BBS
__init__.py # 这个告诉程序用的是什么数据库import pymysql pymysql.install_as_MySQLdb() settings.py import os # Buil ...
- Postman 使用方法详解
转自:https://blog.csdn.net/fxbin123/article/details/80428216 一.Postman背景介绍 用户在开发或者调试网络程序或者是网页B/S模式的程序的 ...
- 个人简历html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Javascript校验密码复杂度的正则表达式
1.密码中必须包含大小字母.数字.特称字符,至少8个字符,最多30个字符. var regex = new RegExp('(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.* ...
- Lattice并购案和我国FPGA发展道路
引用 http://www.cnblogs.com/alifpga/p/9292588.html FPGA作为通信.航天.军工等领域的关键核心器件,是保障国家战略安全的重要支撑基础.近年来,随着数字化 ...
- SpringBoot启动源码探究----configureHeadlessProperty()方法
该方法只做了一件事:设置了一个名为java.awt.headless的系统属性,源码如下: private void configureHeadlessProperty() { System.setP ...