原文博客:https://www.codeobj.com/?p=655
最近正在学习Django,想自己写一些web方面的小东西,由于没有web基础,并且直接上手使用django rest framework + JWT验证,未知的东西比较多,做起来有些吃力,前边遇到的都是个人不知道的问题,不过好在都是前人踩过的并且填好了的坑,今天正好遇到一个小问题,本来想看看别人怎么解决的,结果发现在2016年的时候就有人在官方github上提交了类似的问题,并且还没有解决,于是希望破灭,只能自己想办法
一、Django JWT的JSONWebTokenAuthentication组合IsAuthenticatedOrReadOnly做GET请求时出现401 (Unauthorized)的问题 :
1、官方github的提问地址:
using JSONWebTokenAuthentication with DRF IsAuthenticatedOrReadOnly permission throws 401 on GET
这个作者的意思是要么前端做GET请求时不加Authorization,要么在后端将GET和POST、分开单独写,这两种都不完美,只能算是一个解决方式
2、处于学习阶段,问题解决了就是进步:
1)、在前端使用axios拦截器给header添加JWT认证的Authorization:
Axios.interceptors.request.use(
config => {
let token = store.get("token");
//token存在
if (token) {
console.log(token);
config.headers.Authorization = 'JWT ' + token;
}
return config;
},error => {
NProgress.done();
return Promise.reject(error);
}
);
2)后端想做到除了GET请求不做权限验证,其他所有请求都要经过权限认证,根据网上的说法
class get_menu(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticatedOrReadOnly,)
#IsAuthenticatedOrReadOnly 在JWT token验证不通过时,用户对当前页面进行只读操作
def get(slef,request):
# print(request.TOKEN)
print(request.auth)
return Response({})
结果发现,并不能工作,进行各种尝试,谷歌百度各种查找解决办法,结果就在官方的GitHub找到别人遇到的问题,但是并没有给出一个结果,于是只能自己进行调试。
经过多次debug,发现IsAuthenticatedOrReadOnly不会执行,所以猜测到,由于rest_framework模块与rest_framework_jwt之间不兼容导致验证程序只在JSONWebTokenAuthentication模块中执行,而不会进入到IsAuthenticatedOrReadOnly中。
二、解决问题
上述的问题,如果不知道还挺难,但是找到问题后,我们就可以在JSONWebTokenAuthentication中打断点进行调试,然后就很轻松的把问题给解决了.
如下,只需要写一个继承类,并重写JSONWebTokenAuthentication.get_jwt_value方法,覆盖原方法即可:
from rest_framework.permissions import SAFE_METHODS
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.response import Response
from rest_framework.views import APIView
#继承类,重写JWT认证
class JSONWebTokenAuthenticationInSafeMETHODS(JSONWebTokenAuthentication):
def get_jwt_value(self,request):
"""
重写JWT认证,如果是SAFE_METHODS直接跳过
:param request:
:return:
"""
if request.method in SAFE_METHODS:
return None
return super().get_jwt_value(request)
class get_menu(APIView):
authentication_classes = (JSONWebTokenAuthenticationInSafeMETHODS,)
def get(slef,request):
print(request.auth)
return Response({})
关键代码就在于
class JSONWebTokenAuthenticationInSafeMETHODS(JSONWebTokenAuthentication):
def get_jwt_value(self,request):
"""
重写JWT认证,如果是SAFE_METHODS直接跳过
:param request:
:return:
"""
if request.method in SAFE_METHODS:
return None
return super().get_jwt_value(request)