前言
常见的认证机制:
1.Session
认证
- 保存在服务端(会增加服务器的存储开销)
- 在分布式架构中,维护
Session
的会话同步比较困难 - 有
CSRF
攻击(跨站请求)的风险
2.Token
认证
- 保存在客户端
- 跨语言、跨平台(
json
格式) - 扩展性较强
- 鉴权性能高
更详细讲解点击此处
一、JWT/Json Web Token
-
JWT
是目前最流行的跨域身份验证解决方案,详情点击 -
JWT
所使用的用户模型是Django
自带的用户模型,也就是auth_user
表
1、三大部分组成
- 1.
header
头部- 使用
base64
进行加密,可以被解密 - 只用于声明类型和所使用的加密算法
- 使用
- 2.
playload
载荷- 使用
base64
进行加密,可以被解密 - 存放过期时间、签发用户等非敏感信息
- 使用
- 3.
signature
- 对加密后的
header
+playload
使用HS256
算法进行加密,然后secret
加盐处理 -
SECRET_KEY
在django
项目的setting.py
中,生成项目时自动生成,也可以更改为动态形式
- 对加密后的
1、安装
pip install djangorestframework-jwt
2、使用
1、在主项目全局指定默认使用JWT
认证,所有项目都需要认证;主项目/setting.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
# 使用JWT Token认证
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# Basic类型的认证(账号和密码)
'rest_framework.authentication.SessionAuthentication',
# Session会话认证
'rest_framework.authentication.BasicAuthentication',
],
}
2、添加登录路由(JWT
提供了登录视图),子项目/urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token),
]
3、添加主项目路由,主项目/urls.py
urlpatterns = [
path('users/', include('user.urls'))
]
4、在需要鉴权认证的视图集进行鉴权级别设置(不同的视图页面会有不同的鉴权需求),子项目/views.py
# 登录才可访问,更多的鉴权方式可以看permissions中的内容
permission_classes = [permissions.IsAuthenticated]
5、启动项目并访问即可测试
6、DRF
自带的权限:
AllowAny
IsAuthenticated
IsAdminUser
IsAuthenticatedOrReadOnly
3、改动
- 1、修改
Token
默认过期时间(默认5分钟)-
./site-packages/rest_framework_jwt/settings.py
中'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
设置为5分钟 - 在
主项目/setting.py
中进行修改为1天
-
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1)
}
- 2、修改登录后的响应内容
- 源代码只返回token:
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
}
- 重写,返回用户的id和username,在
utils
路径下创建jwt_handler.py
对上部分代码进行重写
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user_id': user.id,
'username': user.username
}
- 在
主项目/setting.py
中进行修改,使用重写后的设置
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1)
# 原本使用的是源码,现在修改成重写后的
'JWT_PAYLOAD_GET_USERNAME_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler'
}
二、httpie
工具快速调试JWT
的插件:httpie-jwt-auth
当登录返回了JWT
生成的token
值后,后面访问需要鉴权的视图请求中,需要带上固定格式的值:jwt token值
,这样调试起来很不方便,因为token
值很长(jwt
是前缀,可通过设置JWT_AUTH_HEADER_PREFIX
的值进行修改)
1、安装
pip install -U httpie-jwt-auth
2、登录,获取到token
值
http :8000/user/login/ username=xxx password=xxx
3、设置环境变量,简化token
的传递
export JWT_AUTH_TOKEN = 'your token'
export JWT_AUTH_PREFIX='JWT'
4、发出带token
的请求
http -A jwt: 8000/user/projects