问题
I have a basic django rest service, which
- registers a person and
- updates his password.
I want to add jwt authentication on top of it. If I follow the tutorial I would need to add a new url named "api-token-auth" in project's urls.py. But, I don't want to add this new url and want my register call to send a token in response.
Here's my code:
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
def create(self, validated_data):
user = User(
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
def update(self, instance, validated_data):
instance.set_password(validated_data['password'])
instance.save()
return instance
class Meta:
model = User
fields = ('url', 'username', 'password')
lookup_field = 'username'
write_only_fields = ('password',)
views.py
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.exclude(is_superuser=1)
serializer_class = UserSerializer
lookup_field = 'username'
- What should be done to achieve this ? should I call api-auth-token inside my serializer's create method ?
- How does django-rest-framework-jwt handles multiple authentication tokens and correctly identifies which token belongs to which user ? Especially when it doesn't store tokens in a db.
- How can I use this authentication mechanism to limit my user to view/update/delete only his user ?
- How can I use this authentication mechanism to do anything in general. For instance if a user wants to write his name to /tmp/abcd.txt. How can I make sure that only authenticated users would be able to do so ?
- Are there any potential loopholes in this approach. Should I use the same code if my app is going to store lots of classified data ?
回答1:
Question 1: To create a token that would work with django-rest-framework-jwt you can use a function that looks like:
import jwt
from rest_framework_jwt.utils import jwt_payload_handler
def create_token(user):
payload = jwt_payload_handler(user)
token = jwt.encode(payload, settings.SECRET_KEY)
return token.decode('unicode_escape')
you can add this function to the view and create the token once the user has been registered.
Question 2: JWT tokens do not need to be stored int the database you can read me about how JWT works at http://jwt.io/
Question 3 and 4: To use tokens to limit access to a specific view especially an APIView or one of its subclasses or a view provided by Django Rest framework you need to specify the permission classes for example
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
Question 5: One potential loop holes while working with Django Rest Framework is the default permissions that you setup from the settings of your application , if for example you allowAll in the settings it make all the views publicly accessible unless you specifically override the permission classes.
回答2:
Accepted answer has some code that generates token but not shows how to integrate it in serializer/view. Also not sure that manual jwt.encode
is good modern way if we already have jwt_encode_handler
To do this you can create SerializerMethodField
and create token there:
token = serializers.SerializerMethodField()
def get_token(self, obj):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(obj)
token = jwt_encode_handler(payload)
return token
Then add token
field to Meta.fields
.
For full example refer here
来源:https://stackoverflow.com/questions/31147430/how-can-i-make-django-rest-framework-jwt-return-token-on-registration