我正在使用' 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)
答案 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)
上面的代码假设您有UserSerializer
和LoginCustomSerializer
,这可能很简单:
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' )