Django Rest Framework 避免身份验证 JWT
Django Rest Framework avoid authentication JWT
我正在使用 rest_framework_simplejwt
来验证我的用户,但在某些视图中我需要忽略它,因为这些是 public 视图。我想将令牌签入视图流。预期行为是:
在public视图中
- 避免令牌验证:如果有过期或无效的令牌,请忽略它并让我在 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 方法并手动检查用户的方法?谢谢
有一个非常相似的问题。要创建 public 端点,您必须覆盖身份验证器,否则您将 return 401/403 expired/missing 令牌。
但是,public 端点并不意味着它不应该进行身份验证。相反,它应该对 no-auth / expired-auth 有一个响应,对有效 auth 有另一个响应。
我不知道这是否是 "correct" 方法,但这是我遇到同样问题时想出的方法。
像您所做的那样覆盖身份验证器,并添加一个额外的方法来验证您视图中的身份验证器。
例如:
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.
您只需为相关视图指定权限class
from rest_framework.permissions import AllowAny
class SpecificProductApi(APIView):
permission_classes = (AllowAny, )
此权限允许任何人通过URL访问此特定视图。
我通过添加 authentication_classes = []
来完成它
from rest_framework import permissions
class SpecificProductApi(APIView):
permission_classes = [permissions.AllowAny]
authentication_classes = []
您可以在视图中简单地使用 authentication_classes = []
,但这始终会绕过 JWT 身份验证,即使存在带有令牌的有效 Authorization-header 也是如此。您最好按如下方式扩展 JWTAuthentication-class(类似于 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]
。
我正在使用 rest_framework_simplejwt
来验证我的用户,但在某些视图中我需要忽略它,因为这些是 public 视图。我想将令牌签入视图流。预期行为是:
在public视图中
- 避免令牌验证:如果有过期或无效的令牌,请忽略它并让我在 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 方法并手动检查用户的方法?谢谢
有一个非常相似的问题。要创建 public 端点,您必须覆盖身份验证器,否则您将 return 401/403 expired/missing 令牌。
但是,public 端点并不意味着它不应该进行身份验证。相反,它应该对 no-auth / expired-auth 有一个响应,对有效 auth 有另一个响应。
我不知道这是否是 "correct" 方法,但这是我遇到同样问题时想出的方法。
像您所做的那样覆盖身份验证器,并添加一个额外的方法来验证您视图中的身份验证器。
例如:
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.
您只需为相关视图指定权限class
from rest_framework.permissions import AllowAny
class SpecificProductApi(APIView):
permission_classes = (AllowAny, )
此权限允许任何人通过URL访问此特定视图。
我通过添加 authentication_classes = []
from rest_framework import permissions
class SpecificProductApi(APIView):
permission_classes = [permissions.AllowAny]
authentication_classes = []
您可以在视图中简单地使用 authentication_classes = []
,但这始终会绕过 JWT 身份验证,即使存在带有令牌的有效 Authorization-header 也是如此。您最好按如下方式扩展 JWTAuthentication-class(类似于 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]
。