我们将JWT Token与Django REST Framework一起使用。 商店JWT Token和我想在我的数据库中存储JWT Token。因为我将此API用于移动应用。
这里创建JWT令牌
class LoginView(APIView):
permission_classes = [permissions.AllowAny]
def post(self, request, format=None):
"""
Return a Valid token if username and password
is valid for a given client
"""
try:
username = request.data['username']
password = request.data['password']
user = authenticate(username=user.username, password=password)
if user is not None:
if user.is_active:
login(request, user)
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
ind = Individual.objects.filter(user_id=user.id).first()
ind.login_flag = True
ind.save()
这里,我使用了JWT令牌验证
class LogoutView(APIView):
permission_classes = (IsAuthenticated, )
authentication_classes = (JSONWebTokenAuthentication, )
def post(self, request, format=None):
.......
.......
它适用于邮递员的JWT Token验证。但我想在哪里存储令牌以及如何在我的数据库中存储JWT令牌。
答案 0 :(得分:1)
正如@Vijesh在评论中提到的,存储JWT令牌不是正确的方法。从DRF文档中,
与内置的TokenAuthentication方案不同,JWT身份验证 不需要使用数据库来验证令牌。
由于您使用django-rest-framework-jwt包进行JWT令牌身份验证。您还可以使用其apis来检索或刷新令牌。
在用户名和&无法提供密码用于检索或刷新应在Authorization标头中使用带有JWT令牌的受保护URL。因此,登录后,使用收到的令牌构造Authorization标头。 (注意不要错过标题中的JWT部分)
Authorization: JWT <your_token>
卷曲样本
curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/
答案 1 :(得分:1)
使用JWT的一个主要方面是您不想在数据库中存储令牌。存储jwt将破坏无状态身份验证的目的。
您只需验证令牌,加密就会处理其余部分。用于创建的秘密,JWT会对其进行验证,以防止任何阻碍。此外,您需要在ssl上实现jwt实现,以避免令牌劫持。
您通常不会在JWT中存储任何安全数据,但您可以通过加密有效负载来实现。正如JWE规范中所述。
答案 2 :(得分:0)
正如该线程上的其他人所建议的那样,重点不是将JWT存储在数据库中。它用于无状态验证。您应该能够使用机密生成和检索令牌。
在Django中完成此操作的一种方法是使用SECRET_KEY
对JWT中的数据进行编码和解码,例如:
import jwt
from django.conf import settings
from django.contrib.auth import get_user_model
from your_project import custom_exceptions as exc
def get_token_for_user(user, scope):
"""
Generate a new signed token containing
a specified user limited for a scope (identified as a string).
"""
data = {
"user_%s_id" % (scope): str(user.id),
}
return jwt.encode(data, settings.SECRET_KEY).decode()
def get_user_for_token(token, scope):
"""
Given a selfcontained token and a scope try to parse and
unsign it.
If max_age is specified it checks token expiration.
If token passes a validation, returns
a user instance corresponding with user_id stored
in the incoming token.
"""
try:
data = jwt.decode(token, settings.SECRET_KEY)
except jwt.DecodeError:
raise exc.NotAuthenticated("Invalid token")
model_cls = get_user_model()
try:
user = model_cls.objects.get(pk=data["user_%s_id" % (scope)])
except (model_cls.DoesNotExist, KeyError):
raise exc.NotAuthenticated("Invalid token")
else:
return user
函数get_token_for_user
将令牌的user_id
和scope
绑定在一起,并使用密钥对其进行编码。只有知道SECRET_KEY
的人才能解码它。
get_token_for_user
和get_user_for_token
是实用工具,一旦您从HTTP_AUTHORIZATION
标头获得令牌,就可以使用它来验证令牌是否已成功解码和有效。
这些实用程序功能还为您创建的每个令牌都支持scope
。因此,例如,您可以说此特定令牌仅用于authentication
,并将作用域称为authentication
。
这些实用程序功能接受的scope
参数只是一个字符串,因此您可以使用可以想到的任何范围,并且在对特定API调用进行解码时,您会知道令牌应该在什么范围内可用内。
您可以根据需要修改它们,以支持JWT进行身份验证。