目录
django-rest_framework_jwt
作者的信息
优势&劣势
使用
问题
django-rest-framework-simplejwt
作者信息
问题
权限分配
Github
通过他的讲解,我们发现token分为三部分,以"."进行分割,使用Base64编码。
通过作者讲解可知道,添加验证后,需要在Header中添加参数Authorization,内容为 JWT
使用文档
通过使用文档,我们可以简单的了解并进行基本配置。
使用视频
上面是b站的,没有字幕,油管上面有。
JWT 的优势是服务端不再需要存储 Session,使得服务端认证鉴权业务可以方便扩展,避免存储 Session 所需要引入的 Redis 等组件,降低了系统架构复杂度。
JWT 的劣势是由于有效期存储在 Token 中,JWT Token 一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的 JWT Token,如果需要禁用用户,单纯使用 JWT 就无法做到了。
设置
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', # 使用JWT进行权限验证
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 使用JWT进行授权
),
}
# JWT设置
JWT_AUTH = {
# Token编码方法
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
# Token解码方法
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
# payload添加
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
# 获取user_id
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
# 登录后payload返回
'JWT_RESPONSE_PAYLOAD_HANDLER':
'User_set.utils.JWTResponse.jwt_response_payload_handler',
'JWT_SECRET_KEY': settings.SECRET_KEY,
'JWT_GET_USER_SECRET_KEY': None,
'JWT_PUBLIC_KEY': None,
'JWT_PRIVATE_KEY': None,
# 算法
'JWT_ALGORITHM': 'HS256',
# 开启验证
'JWT_VERIFY': True,
# 开启验证过期时间
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
# 一天后Token过期
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
# 开启Token更新
'JWT_ALLOW_REFRESH': True,
# 一天后刷新的Token过期
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
# 默认Token前缀
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_AUTH_COOKIE': None,
}
自定义登录后的返回(添加前端可能需要的信息)
def jwt_response_payload_handler(token, user=None, request=None):
"""为返回的结果添加用户相关信息"""
return {
'token': token,
'user_id': user.id,
'username': user.username
}
未登录前查看api,会发现验证不通过。
登录并得到token
调试方法1:curl
curl安装与使用
curl下载地址
下载.zip文件后解压,进行配置,博主是在Windows系统下编程的,配置如下。
安装成功后,按照curl语法进行测试就好。
调试方法2:postman
Windows下,不想敲命令的话,可以使用postman,Headers参数里面添加上Authorization参数即可。
有两个过期时间,一个是Token的过期时间(JWT_EXPIRATION_DELTA),应该很短,我们应该经常更新Token来保证安全。一个是刷新过期时间(JWT_REFRESH_EXPIRATION_DELTA),用户需要保存密码,自动登录的时间,在此期间如果Token过期了,应该自动进行Refresh。然而,作者把刷新的View写成了如果Token没有过期,那么可以进行刷新??? What???那还有啥用。
问题348
目前,作者在notice中写不再更新了,而这个基本问题都没有解决。
提供一个思路:我们把Token存起来,在更新时,如果已经过期,但是和保存的一样,那么进行更新。
AUTH_USER_MODEL 配置时出了问题,显示路径不对,应该只是包名加类名。例如,auth.User。下面是stack overflow的回答,表示感谢。
stack overflow
Github
他解决上面的问题,使用了access作为Token,一旦它过期,但是刷新时间还没有过期,那么可以使用refresh进行更新,得到新的access和refresh。
Header中,Authorition的前缀不再是JWT 而是Bearer。
他使用了TokenUser作为鉴权用户,直接在代码里面写死了,问题是is_superuser和is_staff都是false,username还是默认为空。那么登录后,我们获取的request.user的类型就是TokenUser类。在Group.objects.filter(user=request.user)时,就会报错。
解决思路:在使用Group等需要参数request.user时,将request.user(TokenUser类型)转为django.concrib.auth.models.user。我们可以通过user=User.objects.get(id=request.user.id)来进行转换。
另外,在Issues下,有人提供了思路,在设置中添加TOKEN_USER_CLASS来让开发者替换TokenUser,但是作者没有merge,用pip install去下载时并没有这段代码,你可以把这段代码下载下来,作为app放到自己的项目里面。
权限分配和验证差不多,具有全局配置,和类的配置,如果你使用方法作为视图的话,可以使用@api_view()方法。在REST官方文档中,没有给出如何对类的某个方法进行权限认证。
阅读源代码,可以发现在APIView里面利用get_permissions方法对permission_classes进行遍历并实例化,对类的某个方法进行权限分配就需要重写get_permissions方法。
# 测试对类的方法进行权限分配
class TestView(generics.RetrieveUpdateDestroyAPIView):
serializer_class = UserInfoSerializer
queryset = User.objects.all()
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
permission_classes = []
if self.request.method == 'GET':
permission_classes.append(GetPermission)
if self.request.method == 'PUT':
permission_classes.append(PutPermission)
return [permission() for permission in self.permission_classes]
有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。