2017-09-30 21 views
1

我使用all-auth/django-rest-auth進行授權。當用戶更改他/她的用戶名時,Django(Django REST Framework)更改用戶的令牌,這使用戶從應用程序註銷;如果其用戶令牌無效,我將該應用設置爲註銷。如何防止JWT Django(all-auth)在其用戶名更新時更改標記?

我想要做的是,即使用戶更改用戶名,電子郵件或User中的任何字段,它也會保留令牌。

這裏是settings.py

REST_USE_JWT = True 
AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth` 
    'django.contrib.auth.backends.ModelBackend', 

    # `allauth` specific authentication methods, such as login by e-mail 
    'allauth.account.auth_backends.AuthenticationBackend', 

    # Facebook OAuth2 
    'social_core.backends.facebook.FacebookAppOAuth2', 
    'social_core.backends.facebook.FacebookOAuth2', 

    # django-rest-framework-social-oauth2 
    'rest_framework_social_oauth2.backends.DjangoOAuth2', 
) 
JWT_AUTH = { 
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=30), 
} 

... 

謝謝!

回答

1

建議:

1)使用戶名作爲一些哈希對象(UUID),並創建新的領域被稱爲username_custom, (更改登錄和註冊視圖)

2)準備好您的模式爲: USERNAME_FIELD = 'username'所以它是在Django

3默認用戶名)從不更新默認字段用戶名和您的令牌永遠不會改變。

1)使用包用戶模型:https://github.com/jcugat/django-custom-user

2)型號舉例

模型
class UserModel(AbstractEmailUser): 
    first_name = models.CharField(max_length=255) 
    last_name = models.CharField(max_length=255) 

    username = models.CharField(max_length=255, db_index=True, unique=True) 
    email = models.EmailField(unique=False, db_index=True) 

    username_custom = models.CharField(max_length=255, db_index=True, unique=True) 

    USERNAME_FIELD = 'username' 

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None): 
     self.first_name = self.first_name.capitalize() 
     self.last_name = self.last_name.capitalize() 
     self.full_name = '{} {}'.format(self.first_name.capitalize(), self.last_name.capitalize()) 
     super(UserModel, self).save(force_insert, force_update) 

    def clean(self): 
     if UserModel.objects.filter(email=self.email, username_custom=self.username_custom).exists(): 
      raise ValidationError('User already exists!') 

你可以看到有新字段username_custom

現在休息api創建用戶。

class UserRegister(APIView): 
    permission_classes = (AllowAny,) 
    authentication_classes =() 

    def post(self, request): 
     data = request.data 

     # or you can check username_custom 
     if UserModel.objects.filter(email=data['email']).exists(): 
      return Response(data={'success': False, 'msg': 'User with email already exists.'}, 
          status=status.HTTP_403_FORBIDDEN) 

     data['username'] = '%s' % uuid.uuid4() 

     serializer = UserRegisterSerializer(data=data) 
     if serializer.is_valid(raise_exception=True): 
      serializer.save() 

      token_data = UserModel.objects.get(email=serializer.data['email']) 
      payload = jwt_payload_handler(token_data) 
      token = jwt_encode_handler(payload) 

      return Response(data={'success': True, 'user': serializer.data, 
            'token': token_prefix + token}, status=status.HTTP_201_CREATED) 


     return Response(data={'success': False, 'msg': serializer.errors}, 
         status=status.HTTP_400_BAD_REQUEST) 

串行

class UserRegisterSerializer(serializers.ModelSerializer): 
    username = serializers.UUIDField() 

    class Meta: 
     model = UserModel 
     fields = ('password', 'email', 'user_type', 'username', 'first_name', 'last_name', 'username_custom',) 

    def create(self, validated_data): 
     user = UserModel.objects.create_user(**validated_data) 

     return user 

您必須preprare更新的方法來檢查唯一的電子郵件字段,以便您沒得到2電子郵件在你的數據庫,或者username_custom任何你想成爲授權。

登錄API

class UserLoginView(APIView): 
    permission_classes = (AllowAny,) 

    def get(self, request, email, password): 

     # or you can check username_custom 
     if not UserModel.objects.filter(email=email.lower()).exists(): 
      return Response(data={'success': False, 'msg': 'Email or password wrong!'}, 
          status=status.HTTP_404_NOT_FOUND) 

     qv = UserModel.objects.get(email=email.lower()) 
     user = authenticate(username=qv.username, password=password) 

     if user: 
      if user.is_active: 
       token_data = UserModel.objects.get(id=user.id) 
       payload = jwt_payload_handler(token_data) 
       token = jwt_encode_handler(payload) 

       return Response(data={'success': True, 
            'token': token_prefix + token}, status=status.HTTP_200_OK) 

     return Response(data={'success': False, 'msg': 'Email or password wrong!'}, 
          status=status.HTTP_400_BAD_REQUEST) 
+0

我覺得你的建議非常好辦法......我們如何設置USERNAME_FIELD =「用戶名」?你可以有任何示例代碼或教程嗎? –

+0

是不是生病給你。 – marin

+0

非常感謝! –

相關問題