Django Rest Framework 避免身份验证 JWT



我正在使用rest_framework_simplejwt来验证我的用户,但在某些视图中我需要忽略它,因为这些是公共视图。 我想将令牌签入视图流。预期行为为:

在公众视野中

  • 避免令牌验证:如果有过期或无效的令牌,请忽略它,让我将其验证到 APIView 中

实际上rest_framework_simplejwt检查令牌并提出401令牌是否无效或过期...

我尝试像这样在 APIView 中禁用authentication_classes

class SpecificProductApi(APIView):
def get_authenticators(self):
if self.request.method == 'GET':
self.authentication_classes = []
return super(SpecificProductApi, self).get_authenticators()

但是如果我在输入方法之前禁用它GET APIView我就无法if reques.user.is_authenticated:因为我禁用了令牌:(

有没有一种方法可以启用输入 api http 方法并手动将用户签入视图?

谢谢

我通过添加authentication_classes = []来完成它

from rest_framework import permissions
class SpecificProductApi(APIView):
permission_classes = [permissions.AllowAny]
authentication_classes = []

您可以简单地在视图中使用authentication_classes = [],但这始终会绕过 JWT 身份验证,即使存在带有令牌的有效授权标头也是如此。你最好扩展JWTAuthentication类如下(类似于Jhon Edwin Sanz Gonzalez的评论(:

from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken

class JWTAuthenticationSafe(JWTAuthentication):
def authenticate(self, request):
try:
return super().authenticate(request=request)
except InvalidToken:
return None

然后在视图中使用authentication_classes = [JWTAuthenticationSafe]

有一个非常相似的问题。要创建公共终结点,您需要强制覆盖身份验证器,否则您将在过期/丢失的令牌上返回 401/403。

但是,公共终结点并不意味着它不应具有身份验证。相反,它应该有一个针对无身份验证/过期身份验证的响应和另一个用于有效身份验证的响应。

我不知道这是否是"正确"的方式,但这就是我面对同样问题时想到的。

像以前一样重写身份验证器,并添加其他方法来验证视图中的身份验证器。

例如:

class SomeApiView(APIView):
def get_authenticators(self):
# Override standard view authenticators.
# Public endpoint, no auth is enforced.
return []
def get_auth(self):
# Return a generator of all authenticators.
return (auth() for auth in self.authentication_classes)
def get_auth_detail(self, request):
# Evaluate each authenticator and return the first valid authentication.
for auth in self.get_auth():
# You probably need try / except here to catch authenticators 
# that are invalid (403/401) in the case of multiple authentication 
# classes--such as token auth, session auth, etc...
auth_detail = auth.authenticate(request)
if auth_detail:
return auth_detail
return None, None
def post(self, request):
# Returns a tuple of (User, JWT), can be (None, None)
user, jwt = self.get_auth_detail(request)  
# Do your magic based on user value.
if user:
# User is authenticated.
else:
# User is anon / not-authenticated.

您只需要为相关视图指定权限类

from rest_framework.permissions import AllowAny
class SpecificProductApi(APIView):
permission_classes = (AllowAny, )

此权限允许任何人通过 URL 访问此特定视图。

最新更新