tokenの利用Pythonベースのログイン登録機能

21777 ワード

Tokenベースの認証方法を使用すると、サービス側でユーザーのログインレコードを保存する必要はありません.大体の流れはこうです.
  • クライアントはユーザ名とパスワードを使用して
  • へのログインを要求する.
  • サービス側は要求を受け取り、ユーザー名とパスワード
  • を検証する.
  • 検証に成功すると、サービス側はTokenを発行し、このTokenをクライアント
  • に送信します.
  • クライアントはTokenを受信した後、クッキーやLocal Storageに
  • を格納することができます.
  • クライアントは、サービス側にリソースを要求するたびに、サービス側が発行するToken
  • を持つ必要がある.
  • サービス側は要求を受け取って、それからクライアント要求の中にあるTokenを検証して、検証が成功すれば、クライアントに要求のデータ
  • を返します.
    1.jwtのデータ戻り設定
    jwt_を書き換えるresponse_payload_handlerはtokenや他のデータを返すことができます
    ログインに成功すると、デバッグツールのResourceのlocalstorageが表示され、tokenが保存されます.
    
        ''' utils/users.py '''
        
        # user          user
    
        def jwt_response_payload_handler(token, user=None, request=None):
    
            return {
                'token':token,
                'username':user.username,
                'user_id':user.id
            }
    
        
        ''' settings.py'''
        
    	REST_FRAMEWORK = {
    	    'DEFAULT_AUTHENTICATION_CLASSES': (
    	        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    	        'rest_framework.authentication.SessionAuthentication',
    	        'rest_framework.authentication.BasicAuthentication',
    	    ),
    	}
    
        #   jwt        
        JWT_AUTH = {
            'JWT_RESPONSE_PAYLOAD_HANDLER':'utils.user.jwt_response_payload_handler'
        }
    
           
    
    

    2.登録に成功したらtokenに戻る
    筆者が出てきたバグ:createメソッドでuserオブジェクトにtokenフィールドを追加しなかった場合、アカウントを登録し、その後createメソッドにtokenフィールドを追加した後、このアカウントでログインすると、そのオブジェクトにtokenフィールドがないため、tokenを要求できません.
    登録完了確認後にtokenが生成されます.すなわち、データの入庫後に登録が完了します.tokenが登録完了をクリックすると、createでsaveが入庫した後に登録が完了する一連のイベントがトリガーされます.
    tokenのコードを生成するには:
    
        def create():
    
            ...
    
            #                  
            from rest_framework_jwt.settings import api_settings
    
            #     2   
            jwt_payload_handler = api.settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api.settings.JWT_ENCODE_HANDLER
    
            # 1.jwt_payload_handler               ,       user    
            #       ,        
            payload = jwt_payload_handler(user)
            # 2.   payload              token
            token = jwt_encode_handler(payload)
    
            #         token
            #                       
            #         
            user.token = token
    
    
            return user
    
    
        ######      user.token = token         #########
    
        def Person(object):
            name = ''
        
        p = Person()
        p.name = 'it'
        print(p.name)
    
        #                          
        p.age = 20
        print(p.age)
    
        #       
        p2 = Person()
        print(p2.age)
    
    
    
    
    
    
        
        ''' serializer.py  ''''
    
        class RegisterCreateSerializer(serializers.ModelSerializer):
    
            ...
    
            #      
            token = serializers.CharField(label='token',read_only=True)
            # token          (     JSON)       ,           read_only
            #   read_only        token      
            # read_only                 
            class Meta:
                    model = Users
                    fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow', 'token')  #   token
           
    
    
    	''' js/register.js '''
    
    

    フロントエンドファイルにtokenを追加保存
    
    	var vm = new Vue({
    	    ...
    	    methods: {
    	        on_submit: function(){
    	            axios.post(...)
    	                .then(response => {
    	                    //          
    	                    sessionStorage.clear();
    	                    localStorage.clear();
    	                    localStorage.token = response.data.token;
    	                    localStorage.username = response.data.username;
    	                    localStorage.user_id = response.data.id;
    	                    location.href = '/index.html';
    	                })
    	                .catch(...)
    	        }
    	    }
    	})
    
    

    3.マルチアカウント登録認証
    サポートユーザー名と携帯電話番号を追加してもログインアカウントとして使用できます
    JWT拡張のログインビューは、ユーザー名とパスワードを受信したときにDjangoの認証システムで提供されているauthenticate()を呼び出して、ユーザー名とパスワードが正しいかどうかを確認します.
    Django認証システムの認証バックエンド(主にauthenticateメソッド)を変更することで、ログインアカウントをユーザー名でも携帯電話番号でもサポートできます.
    Django認証システムの認証バックエンドを変更するにはdjangoを継承する必要がある.contrib.auth.backends.ModelBackend、authenticateメソッドを書き換えます.
    authenticate(self,request,username=None,password=None,*kwargs)メソッドのパラメータの説明:
    request今回の認証のリクエストはusername今回の認証で提供されたユーザーアカウントpassword今回の認証で提供されたパスワードを独り占めしたいのですが、ユーザー名でも携帯電話番号でもログインできるようにしたいのですが、authenticateメソッドではusernameパラメータはユーザー名または携帯電話番号を表します.
    authenticateメソッドを書き換える考え方:
    usernameパラメータに基づいてユーザーUserオブジェクトを検索します.usernameパラメータはユーザー名、携帯電話番号のいずれかです.
    Userオブジェクトが見つかったら、Userオブジェクトのcheck_を呼び出します.passwordメソッドパスワードが正しいかどうかを確認
    
        ''' utils/users.py '''
    
        def get_user_by_account(username):
            #                            
            try:
                if re.match('1[3-9]\d{9}',username):
                    #            
                    user = Users.objects.get(mobile=username)
                else:
                    user = Users.objects.get(username=username)
            except Users.DoesNotExist:
                user = None
            
            return user
    
        class UsernameMobileAuthModelBackend(ModelBackend):
    
            def authenticate(self,request,username=None,password=None,**kwargs):
                
                # 1.               
                user = get_user_by_account(username)
    
                # 2.   
                if user is not None and user.check_password(password):
    
                    return user
                
                return None
    
        class SettingsBackend(object):
            """
            Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.
    
            Use the login name and a hash of the password. For example:
    
            ADMIN_LOGIN = 'admin'
            ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
            """
    
            def authenticate(self, request, username=None, password=None):
                # 1.                     ,           ,            
                #              
                user = get_user_by_account(username)
    
                # 2        ,       
                if user is not None and user.check_password(password):
                    return user
                return None
    
            def get_user(self, user_id):
                try:
                    return Users.objects.get(pk=user_id)
                except Users.DoesNotExist:
                    return None
    

    認証バックエンドのクラスを変更する必要がありますプロファイルでDjangoにカスタム認証バックエンドを使用するように通知します
    
        '''settings.py '''
    
        #         
        AUTHENTICATION_BACKENDS = [
            # 'utils.users.UsernameMobileAuthModelBackend',
            'utils.users.SettingsBackend'
        ]
    
            #          
            # {
            #   "non_field_errors": [
            #     "             。"
            #   ]
            # }
    
    

    Django REST framework JWTはtokenを取得するためにログインするビューを提供し、直接使用することができ、usersアプリケーションのurlsにルーティング情報を追加します.
      
        ''' urls.py '''
        
        from rest_framework_jwt.views import obtain_jwt_token
      
        urlpatterns = [
            #      
            url(r'^auths/',obtain_jwt_token),
        ]