Django JWT的JSONWebTokenAuthentication组合IsAuthenticatedOrReadOnly做GET请求时出现401 (Unauthorized)的问题

Django admin 2年前 (2019-02-16) 125次浏览 4个评论 扫描二维码

最近正在学习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)

codeobj , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Django JWT的JSONWebTokenAuthentication组合IsAuthenticatedOrReadOnly做GET请求时出现401 (Unauthorized)的问题
喜欢 (0)
[a37free@163.com]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(4)个小伙伴在吐槽
  1. 你好,我使用的是 https://github.com/davesque/django-rest-framework-simplejwt 这个,根据他的文档我也配置了settings.py 路由中也能获取到token 但是视图中怎么使用呢,我新建了一个视图,视图中继承的是django.views.view。前端发起请求后,不填token也能获取到数据,是我配置的不对吗,还是看您这个是需要继承APIView 才行。
    fenn2019-02-17 11:13 回复
    • 那您在后端是能获取到还是获取不到token呢。如果是获取不到,网上比较多的就是类似于这种config.headers.Authorization = token; //权限验证信息 我是在拦截器中做的,目前来看这个方式可行,在view中直接是使用request.auth就能拿到数据。 config.headers.token = token;这种方式还没走通,正在测试中
      Destiny2019-02-18 09:04 回复
    • Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b很多都是用的这种
      Destiny2019-02-18 09:12 回复