Django JWT-Auth我也有登录API。我可以在登录时生成令牌并发送到前端吗?

时间:2017-09-14 14:52:46

标签: django django-rest-framework jwt

  

我正在使用' rest_framework_jwt.authentication' 并且我还有Login API,如果我在默认 auth-token API上生成令牌,那么是使用Login API吗?

所以我可以在执行登录API时生成令牌,如果成功,则将生成的令牌发送回前端。

urls.py

url(r'^login/$', views.UserLoginAPIView.as_view(), name='login'),
url(r'^api/auth/token/', obtain_jwt_token),

serializers.py

class UserLoginSerializer(ModelSerializer):
token = CharField(allow_blank=True, read_only= True)
email = EmailField(label='Email Address', allow_blank= True)

class Meta:
    model = User
    fields = [
        'email',
        'password',
        'token'
    ]

    extra_kwargs = {"password":
                        {"write_only": True}
                        }

def validate(self, data):
    user_obj = None
    email = data.get("email", None)
    password = data["password"]
    if not email:
        raise ValidationError('A username or email is required to login')
    user = User.objects.filter(
            Q(email=email) 
        ).distinct()
    if user.exists() and user.count() == 1:
        user_obj = user.first()
    else:
        raise ValidationError("this email is not valid")

    if user_obj:
        if not user_obj.check_password(password):
            raise ValidationError("incorrect creadeintial try again") 
    data["token"] = "SOME BLANK TOKEN"
    return data

view.py

class UserLoginAPIView(APIView):
permission_classes = [AllowAny]
serializer_class = UserLoginSerializer

def post(self, request, *args, **kwargs):
    data = request.data
    serializer = UserLoginSerializer(data=data)
    if serializer.is_valid(raise_exception=True):
        new_data = serializer.data
        return Response(new_data, status=HTTP_200_OK)
    return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

2 个答案:

答案 0 :(得分:0)

直接从网络前端调用API并不是一个好主意。如果您已使用会话登录,则不需要任何令牌。在大多数情况下,有一个调用api服务器的Web服务器。 API服务器使用令牌对用户进行身份验证。令牌存储在Web服务器的会话表中。 Android或IOS应用程序可以直接调用API并获取令牌。

答案 1 :(得分:0)

您只需要一个登录API,因此请选择是自己编写还是使用提供的API。如果你想要的只是返回令牌,只需使用提供的令牌即可。但您可能希望在自定义登录中执行其他操作。例如,您还可以返回有关用户的更多信息(例如头像)。

在登录时返回令牌很有意义,所以你只需要用

返回它
from rest_framework_jwt.settings import api_settings

def get_jwt_token(user):
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    payload = jwt_payload_handler(user)
    return jwt_encode_handler(payload)

然后你可以得到像这样的JWT标记

data["token"] = get_jwt_token(request.user)

但我个人认为最好不要从序列化验证器中做到这一点。以下是我实现自己的登录功能的方法:

from django.contrib.auth import authenticate, login
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.parsers import JSONParser

class APILoginViewSet(APIView):
  """
  Returns user info and tokens if successful
  """

  @csrf_exempt
  def post(self, request, format=None):
    """
    Secondary login method. Uses email and password
    Recommendation: Use `POST:/api/v1/auth/api-jwt-auth/` instead
    """
    data = JSONParser().parse(request)
    serializer = LoginCustomSerializer(data=data)

    if serializer.is_valid():
        email = serializer.data.get('email')
        password = serializer.data.get('password')

        if not request.user.is_anonymous:
          return Response('Already Logged-in', status=status.HTTP_403_FORBIDDEN)

        user = authenticate(email=email, password=password)

        if user is not None:
          if user.is_active:
            login(request, user)

            serialized = UserSerializer(user)
            data = serialized.data

            # Also return JWT token
            data['jwt'] = get_jwt_token(user)

            return Response(data)
          else:
            return Response('This user is not Active.', status=status.HTTP_401_UNAUTHORIZED)
        else:
          return Response('Username/password combination invalid.', status=status.HTTP_401_UNAUTHORIZED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

上面的代码假设您有UserSerializerLoginCustomSerializer,这可能很简单:

class LoginCustomSerializer(serializers.Serializer):
  email = serializers.EmailField(max_length=200)
  password = serializers.CharField(max_length=200)

class UserSerializer(serializers.ModelSerializer):

  class Meta:
    model = User
    fields = ('id', 'email', 'username', 'created_at', 'name')
    read_only_fields = ( 'email', 'username', 'created_at' )