我正在使用基于Django Token的身份验证。 (JWT Token由AWS Cognito等第三方生成,我们只会验证签名和到期时间。)
此REST应用程序不具有任何用户模型,任何使用API调用的人都只需要通过JWT令牌进行身份验证。
class JSONWebTokenAuthentication(TokenAuthentication):
def authenticate_credentials(self, jwtToken):
try:
payload = jwt.decode(jwtToken, secret_key,verify=True)
# user = User.objects.get(username='root')
user = AnonymousUser()
except (jwt.DecodeError, User.DoesNotExist):
raise exceptions.AuthenticationFailed('Invalid token)
except jwt.ExpiredSignatureError:
raise exceptions.AuthenticationFailed('Token has expired')
return (user, payload)
在视图中:
@api_view(["POST"])
@authentication_classes((JSONWebTokenAuthentication,))
@permission_classes((AllowAny,))
以上过程中,根本不跟踪令牌。使用/不使用令牌,APi调用正在运行。如果我在下面进行了两次更改,它就会正常工作。
user = User.objects.get(username='root')
#user = AnonymousUser()
@permission_classes((IsAuthenticated,))
一种方法是,在我的应用程序中至少有一个用户并引用该用户[此webapp可能会在需要时扩展到任意数量的实例,因此插入相同的用户使用相同的"用户名"必须自动化。 ]。但相反,我可以消除"用户"身份验证中的概念?
答案 0 :(得分:3)
使用django-rest-framework-simplejwt可以将DEFAULT_AUTHENTICATION_CLASSES
设置为使用JWTTokenUserAuthentication,即使没有用户也可以验证令牌。
答案 1 :(得分:2)
Django REST框架主要假设请求是基于用户进行身份验证的,但它们确实为身份验证匿名请求提供支持。但它通过给予匿名用户某些权限来“验证(django)用户是真实的”标准假设脱颖而出。您的第一个案例的问题是具有“允许任何”的权限装饰器。
我建议有一个虚拟的Django用户。 (它也不会阻止你扩展到任何数量的实例)。
使用
user = User.objects.get_or_create(username='whatever')[0]
而不是
user = AnonymousUser()
现在将权限装饰器更改为
@permission_classes((IsAuthenticated,))
除非您设置密码,否则此用户无法由任何人登录,而且登录时此用户无法访问您的API调用。访问API的唯一方法是发送有效的令牌。
希望这有帮助。
答案 2 :(得分:1)
有时候,您实际上真的不需要用户,例如服务器到服务器的通信。这是一个解决方案。
覆盖AnonymousUser的is_authenticated属性,您可以使用
from django.contrib.auth.models import AnonymousUser
class ServerUser(AnonymousUser):
@property
def is_authenticated(self):
# Always return True. This is a way to tell if
# the user has been authenticated in permissions
return True
仅在您的自定义身份验证中返回这种新型用户
class CustomServerAuthentication(authentication.BaseAuthentication):
keyword = 'Token'
def authenticate(self, request):
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != self.keyword.lower().encode():
raise exceptions.AuthenticationFailed('Invalid token header')
if len(auth) == 1:
raise exceptions.AuthenticationFailed('Invalid token header. No credentials provided.')
elif len(auth) > 2:
raise exceptions.AuthenticationFailed('Invalid token header. Token string should not contain spaces.')
token = auth[1].decode()
if not (settings.CUSTOM_SERVER_AUTH_TOKEN == token):
raise exceptions.AuthenticationFailed('You do not have permission to access this resource')
user = ServerUser()
return user, None
答案 3 :(得分:0)
尝试验证JWT令牌是否存在。似乎如果它没有,有效载荷只是None而用户是匿名的
答案 4 :(得分:0)
你可以使用 User 模型而无需向数据库插入数据 使用:
user = User(id=22,username="someone")
代替:
user = User.objects.get_or_create(username="someone")
或
AnonymousUser()