1. JWT安装配置
1.1 安装JWT
pip install djangorestframework
-jwt
==1.11.0
1.2 syL/settings.py 配置jwt载荷中的有效期设置
JWT_AUTH
= {
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_EXPIRATION_DELTA': datetime
.timedelta
(days
=1),
'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',
}
1.3 syl/settings.py jwt结合DRF进行认证权限配置
REST_FRAMEWORK
= {
...
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication', DRF中配置JWT认证
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
1.4 user/urls.py 增加获取token接口和刷新token接口
from django
.urls
import include
, path
from rest_framework
.authtoken
.views
import obtain_auth_token
from user
import views
from rest_framework
.routers
import SimpleRouter
, DefaultRouter
from rest_framework_jwt
.views
import obtain_jwt_token
, refresh_jwt_token
urlpatterns
= [
path
('index/', views
.index
),
obtain_jwt_token
),
refresh_jwt_token
),
include
('rest_framework.urls',
namespace
='rest_framework')),
]
urlpatterns
+= router
.urls
1.5 在urls/utils.py 中重写jwt_response_payload_handler
def jwt_response_payload_handler(token
, user
=None, request
=None, role
=None):
"""
自定义jwt认证成功返回数据
:token 返回的jwt
:user 当前登录的用户信息[对象]
:request 当前本次客户端提交过来的数据
:role 角色
"""
if user
.first_name
:
name
= user
.first_name
else:
name
= user
.username
return {
'authenticated': 'true', 'id': user
.id,
"role": role
,
'name': name
,
'username': user
.username
,
'email': user
.email
,
'token': token
,
}
2. postman测试接口
2.1 测试登录接口,获取token
'''自定义认证和权限优先级更高, 可以覆盖settings.py中的 '''
permission_classes
= (MyPermission
,)
authentication_classes
= (JSONWebTokenAuthentication
,)
2.2 使用获得的token获取所有用户信息
http
://192.168.56.100:8888/user
/user
/
3. 源码分析
from rest_framework
.views
import APIView
class JSONWebTokenAPIView(APIView
):
"""
Base API View that various JWT interactions inherit from.
"""
permission_classes
= ()
authentication_classes
= ()
def get_serializer_context(self
):
"""
Extra context provided to the serializer class.
"""
return {
'request': self
.request
, 'view': self
,
}
def get_serializer_class(self
):
"""
Return the class to use for the serializer. Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
assert self
.serializer_class
is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self
.__class____name__
)
return self
.serializer_class
def get_serializer(self
, *args
, **kwargs
):
"""
Return the serializer instance that should be used for validating and deserializing input, and for serializing output.
"""
serializer_class
= self
.get_serializer_class
()
kwargs
['context'] = self
.get_serializer_context
()
return serializer_class
(*args
, **kwargs
)
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
)
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
)