Django認証&承認


認証&承認の概念を理解し、Django Westagramプロジェクトに認証の必須要素パスワード暗号化を適用し、承認された必須要素JWTが発行する

認証


認証はプレイヤーの身元を確認するプログラムです.つまり、プレイヤーの身元とパスワードを確認する過程です.認証プロセスを通じて、誰が私たちのサービスを使用しているのか、どのように私たちのサービスを使用しているのかを追跡することができます.
ログイン手順は次のとおりです.
1.アイデンティティ、パスワード生成
2.ユーザパスワードを暗号化してDBに保存する
3.ユーザが入力したIDとパスワードをDBの情報と比較する
4.一致する場合、ログインは成功しました
5.ログインが成功すると、サーバはクライアントにアクセストークンを送信する
6.ユーザは、次回の要求時にアクセストークンを添付してサーバに送信する

パスワードの暗号化


パスワードを暗号化せずにデータベースに保存すると、ハッカーに攻撃されたときにそのまま露出する可能性があるので、パスワードを暗号化して保存します.

たんほうこうハッシュかんすう


元のメッセージを変換し、暗号化メッセージの要約を生成します.元のメッセージはこのように暗号化できますが、暗号化されたメッセージは元のメッセージを認識できないため、一方向と呼ばれます.
一方向ハッシュ関数を使用すると、値が少し変化してもdigest値が完全に変化し、avanceと呼ばれる導出が困難になります.
一方向ハッシュ関数にももちろん欠点がある.
元の情報が同じであれば、同じ要約値しか生成されず、ハッカーが大量の要約を取得する危険性が高まります.

salting & keystretching


一方向ハッシュ関数の欠点を補うために,この2つの方法を提案した.
実際の元のメッセージに加えて、ランダムデータを追加することによってハッシュ値を抽出することをsaltingと呼ぶ.元の情報が検出されてもsaltingedgestのパスワードマッチングは困難である.
saltingとhassingを複数回繰り返してキーを増やし,より理解しにくくする過程がkeystretchingである.keystretchingを使用すると、ランダムに導入されたハッシュ値の計算に要する時間を増やすことができます.

bcrypt


saltingとkeystretchingの両方で実現されるハッシュ関数で最も広く使用されている.同じソース・メッセージをsalting、ハッシュ値、および繰返し回数を使用してハッシュ値にハッシュしても、まったく異なる値が得られます.

権限


承認とは、ユーザが要求に応じた権限を持っているかどうかを確認するプログラムである.
承認の手順は以下の通りです.
  • 認証プロセスによってaccesstokenが生成されます.accesstokenには、ユーザー情報を表示できる情報(例えばuserid)が含まれている必要があります.
  • ユーザが要求を送信するとaccesstokenを添付して送信する.
  • サーバは、ユーザが送信したアクセストークンを復号する.
  • によりデータを復号してユーザidを取得する.
  • ユーザーidを使用して、データベースでユーザーの権限を確認します.
  • プレイヤーは、リクエストを処理するのに十分な権限を持っている.
  • ユーザは、無許可で、無許可の応答(401)または他のエラーコードを発行する.
  • JWT (Json Web Token)


    これはaccesstokenを生成する最もよく知られている方法の一つである.ユーザとサーバは、Jsonデータを暗号化することによって対話することができる.すべての情報は自分で持っていて、自分で受け入れることができて、2つのオブジェクトの間で簡単に伝えることができます
    JWTは、Header、Payload、Signatureの3つの文字列で区切られています.

    header


    トークンタイプとハッシュアルゴリズム情報を持つ.

    payload


    コインに含まれる情報で、情報の一部をname:valueのクレームと呼びます.
    claimのタイプは次のとおりです.
    登録Claim:事前定義クレーム
    Public Claim       : 声明は情報を公開することを目的としている.
    Private Claim      : クライアントとサーバ間の交渉で使用されるクレーム

    signature


    ヘッダの符号化値と負荷の符号化値、および所与のsecret keyを復号化することによって生成される.

    Westagram認証の実施

    class SignUpView(View):
        def post(self, request):
            try:
                data            = json.loads(request.body)
                name            = data['name']
                email           = data['email']
                password        = data['password']
                phone_number    = data['phone_number']
    
                hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
                decode_password = hashed_password.decode('utf-8')
    
                validate_email(email)
                validate_password(password)
    
                if User.objects.filter(email=email).exists():
                    return JsonResponse({'message':'Your email is already exists'}, status=400)
    
                User.objects.create(
                    name         = name,
                    email        = email,
                    password     = decode_password,
                    phone_number = phone_number
                )
    
                return JsonResponse({'message':'SUCCESS'}, status=201)
    
            except KeyError:
                return JsonResponse({'message':'KeyError'}, status=400)
    
            except ValidationError as e:
                return JsonResponse({'message':(e.message)}, status=400)
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    decode_password = hashed_password.decode('utf-8')
    暗号化関数は、Bytesデータのみを暗号化できるため、パスワードを符号化してBytesデータに変換できます.エンコードされたpasswodデータはDBに格納できないため、decodeはBytesデータからstrデータに変換される.
    最終的に復号されたハッシュ値をDBに保存します.

    Westagram認証の実施

    from django.conf            import settings
    
    class SignInView(View):
        def post(self, request):
            try:
                data     = json.loads(request.body)
                email    = data['email']
                password = data['password']
                user     = User.objects.get(email=email)
        
                if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')):       
                    return JsonResponse({"message":"INVALID_USER"}, status=401)
    
                access_token = jwt.encode({'id':user.id}, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
                
                return JsonResponse({'access_token':access_token}, status=200)
    
            except KeyError:
                return JsonResponse({'message':'KEY_ERROR'}, status=400)
    
            except User.DoesNotExist:
                return JsonResponse({"message":"INVALID_USER"}, status=401)
    
    user     = User.objects.get(email=email)
        
                if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')):       
                    return JsonResponse({"message":"INVALID_USER"}, status=401)
    
                access_token = jwt.encode({'id':user.id}, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
                
                return JsonResponse({'access_token':access_token}, status=200)
    
    SECRET KEY、ALGORITHM、my settingsなどの環境変数を作成します.pyによって管理されます.my_settings.pyファイルは、環境変数管理の役割としてのみ使用されるビューです.pyまたはmodel.pyから直接インポートして使用すると、ビューが表示されます.pyファイルはmy settingsです.pyファイルに依存します.環境変数ファイルがmy settingsの場合.pyではなく別の方法で管理されている場合は、ビューです.pyのコードも修正する必要があります.
    だからmy settings.pyの環境変数をインポートする場合、Djangoから直接インポートしません.conf import settingsを使用して設定します.pyからインポートします.
    bcrypt.checkpw関数はbcryptです.checkpw(ユーザから入力されたパスワード、格納された暗号化パスワード)のフォーマットがあります.
    だからbcrypt.checkpw関数を使用して2つのパスワードを比較し、異なる場合はfalseを返し、falseの場合は401エラーメッセージを返します.
    2つのパスワードが同じ場合はaccesstokenを作成して返します.