Project 1. Marketkurly clone|インプリメンテーションログインエンドポイント&JWT認証データレコーダ


実装画面



1.ログインAPI


会員からAPIを入力して情報を受信するだけなので、APIにログインするのは簡単です.最初は、ユーザー名とパスワードが間違っていれば、それぞれINVALID_ACCOUNTINVALID_PASSWORDの情報回送を実現し、個人情報保護などの理由でIDとパスワードが誤った情報を区別しない傾向のフィードバックを受け、INVALID_USER回送情報に統一された.
実施内容
  • エラー処理
    -IDが存在しない場合は、USER_NOT_EXISTのメッセージが返されます.
    -IDまたはパスワードが間違っている場合は、INVALID_USERのメッセージが返されます.
    -他のエラーが発生した場合、KEY_ERRORメッセージ
  • を返す.
  • ログイントークンの作成(JWT)
    -生成されたタグの内容(ペイロード)には、24時間として指定された有効期限が含まれます(datetime.utcnow()+timedelta(hours=24)).
    -成功時にaccess_token
  • 回戻る
    class SigninView(View):
        def post(self, request):
            data = json.loads(request.body)
    
            try:
                if not User.objects.filter(account=data['account']).exists():
                    return JsonResponse({"message":"USER_NOT_EXIST"}, status=404)
    
                if User.objects.filter(account=data['account']).exists():
                    user      = User.objects.get(account=data['account'])
                    hashed_pw = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
    
                    if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
                        access_token = jwt.encode({'id':user.account, 'exp': datetime.utcnow() + timedelta(hours=24)}, SECRET_KEY, ALGORITHM).decode('utf-8')
    
                        return JsonResponse({"ACCESS_TOKEN":access_token}, status=201)
    
                    return JsonResponse({"message": "INVALID_USER"}, status = 401)
    
                return JsonResponse({"message":"INVALID_USER"}, status=401)
    
            except KeyError:
                return JsonResponse({"message":"KEY_ERROR"}, status=400)
    

    2.JWT認証デコーダ


    サイトを利用すると、ショッピングバスケットなど会員のみが利用できる機能です.このとき,ログイン時に発行されたトークンを用いて,そのユーザがログイン済みであるか有料であるかを区別する.
    Decoratorを使用すると、エンコーディングを必要とせずにログインするたびにログインの構文をチェックすることができます.レコーダは@함수명と表示されます.
    JWT認証デコーダを実装するために、USER appにおいてutils.pyというファイルが作成され、重畳関数を使用してデコーダが作成される(@signin_decorator).Decoratorを実装する間、JWTとオーバーラップ関数の概念を理解することができ、これは非常に役立ち、有益な時間である.
    ちなみにデコレーションを使うためには、from .utils import signin_decoratorを導入して使うだけです.

    1)装飾品の実施


    実施内容
  • エラー処理
  • HTTP要求が許可されていない場合(None)、INVALID_LOGINに戻る
  • tokenが期限切れになった場合は、EXPIRED_TOKENを返します.
  • token復号エラーが発生した場合はINVALID_TOKENに戻ります
  • ユーザが存在しない場合はINVALID_USER
  • に戻る.
  • 無効tokenの場合はNEED_LOGINを返します
  • HTTPリクエストにおけるauthorizationヘッダ値get
  • JWT暗号化時に使用するSECRET KEYおよびALGORITHMを使用してトークンを復号し、token_payload変数
  • に割り当てる.
  • 復号JWTのユーザIDを変数(user)
  • に割り当てる.
  • が要求するユーザと実際のユーザとが一致するか否かを比較する(request.user = userはdecoratorを用いてjwt認証を行うたびに使用される重要な情報である)
  • .
    import json, jwt
    
    from django.http             import JsonResponse
    from django.core.exceptions  import ObjectDoesNotExist
    
    from my_settings             import SECRET_KEY, ALGORITHM
    from .models                 import User
    
        
    def signin_decorator(func):
        def wrapper(self, request, *args, **kwargs): 
    
            access_token    = request.headers.get("Authorization", None)  
    
            if "Authorization" ==  None:
                return JsonResponse({"message":"INVALID_LOGIN"}, status=401)
            
            try:
                token_payload   = jwt.decode(access_token, SECRET_KEY, ALGORITHM)
                user            = User.objects.get(account=token_payload['id']) 
                request.user    = user
    
                return func(self, request, *args, **kwargs)
    
            except jwt.ExpiredSignatureError:
                return JsonResponse({"message":"EXPIRED_TOKEN"}, status=401) 
    
            except jwt.DecodeError: 
                return JsonResponse({"message":"INVALID_TOKEN"}, status=401) 
    
            except User.DoesNotExist:
                return JsonResponse({"message":"INVALID_USER"}, status=401) 
           
            except jwt.InvalidTokenError:
                return JsonResponse({"message":"NEED_LOGIN"}, status=401)
    
        return wrapper

    2)試験記録器


    作成したデコーダが正常に動作しているか確認したいのですが、担当している部分にデコーダを追加していない部分があるのでtest viewを作成してみました.

    views.py

    class TestDecoratorView(View):
         @signin_decorator
         def get(self, request):
         
         	print(f'user:{request.user}')
            return JsonResponse({"message":"success"})
    

    urls.py

    from django.urls import path
    from .views import SignupView, SigninView, TestDecoratorView
     
    urlpatterns = [
    	path('/signup', SignupView.as_view()),
    	path('/signin', SigninView.as_view()),
    	path('/decoratortest', TestDecoratorView.as_view())
    ]
    前述したように、作成後に通信を行うことで、データレコーダが起動されたか否かを判定することができる:)