1.登录接口
2.刷新接口
3.自定义返回格式
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_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA':datetime
.timedelta
(hours
=24),
'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',
],
'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
router
= DefaultRouter
()
router
.register
(r
'user', views
.UserViewSet
)
urlpatterns
= [ path
('index/', views
.index
),
path
('login/', obtain_jwt_token
),
path
('refresh/', refresh_jwt_token
),
path
('api-auth/', include
('rest_framework.urls',
namespace
='rest_framework')),
]
urlpatterns
+= router
.urls
1.5 在user/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
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wpi03CZl-1602030044992)(C:\Users\Lucky\Pictures\Camera Roll\jwt安装配置12.png)]
'''自定义认证和权限优先级更高,可以覆盖setting.py中的'''
permission_classes
= (MyPermission
)
authentication_classes
= (JSONWebTokenAuthentication
,)
2.2 使用获得的token获取所有用户信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bnYFwiEb-1602030044995)(C:\Users\Lucky\Pictures\Camera Roll\jwt安装配置1.png)]
3.源码分析
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
)
编写注册接口
1.1 user/urls.py 中添加路由
1.2 user/views.py 中写注册视图函数
urlpatterns
= [ path
('register/', views
.RegisterView
.as_view
()),
1.2 user/views.py 中写注册视图函数
class RegisterView(APIView
):
permission_classes
= (AllowAny
,)
def post(self
,request
):
"""
接收邮箱和密码, 前端校验两遍一致性, 注册成功后返回成功, 然后用户自行登录获取token
1. 随机用户名
2. 生成用户
3. 设置用户密码
4. 保存用户 :param request:
:return: {'code':0,'msg':'注册成功'}
"""
email
= request
.data
.get
('email')
password
= request
.data
.get
('password')
if all([email
,password
]):
pass
else:
return Response
({'code':400,'msg':'参数不全'})
rand_name
= self
.randomUsername
()
user
= User
(username
=rand_name
,email
=email
)
user
.set_password
(password
)
user
.save
()
return Response
({'code':0,'msg':'OK'})
def randomUsername(self
):
"""
生成随机用户名: 格式: SYL + 年月日时分 + 5位随机数
:return:
"""
d
= datetime
.datetime
.now
()
base
= 'SYL'
time_str
= '%04d%02d%02d%02d%02d'% (d
.year
, d
.month
, d
.day
, d
.hour
, d
.minute
)
rand_num
= str(random
.randint
(10000, 99999))
return base
+ time_str
+ rand_num
2.重写django认证
2.1 syl/settings.py 中指定自定义后端认证函数位置
2.2 user/utils.py 中重写认证函数
class EmailAuthBackend:
def authenticate(self
, request
, username
=None, password
=None):
try:
user
= User
.objects
.get
(username
=username
)
except Exception
as e
:
print(e
)
user
= None
if not user
:
try:
user
= User
.objects
.get
(email
=username
)
except Exception
as e
:
print(e
)
user
= None
if user
and user
.check_password
(password
):
return user
else:
return None
def get_user(self
, user_id
):
try:
return User
.objects
.get
(pk
=user_id
)
except User
.DoesNotExist
:
return None
if user and user.check_password(password):
return user
else:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None