TIL 31. 認証と承認(Bcrypt、JWT)


1.認証と承認


基本登録とログインプロセス


  • ユーザー登録時にIDとパスワードを入力

  • パスワードは暗号化によりDBに保存されます

  • ユーザーログイン時にIDとパスワードを入力

  • 入力したパスワードを暗号化し、データベース内のユーザーパスワードと比較します.

  • 一致する場合、access_tokenが生成され、クライアントに送信される

  • ログインに成功したユーザーは、以降のrequestヘッダにaccess_tokenを添付して送信されます.(Authorization)
  • 認証


    システムにアクセスするときに、登録されたユーザーであることを確認します.
    ログイン時にID、パスワードなどの一意の値を使用してユーザーIDを確認するには

    権限


    システムアクセス後、認証されたユーザーに特定の権限を付与します.
    ユーザーレベルや権限に応じて機能の使用を制限できます.

    2.パスワード暗号化(bcrypt)


    2-1. パスワードの暗号化が必要


    個人情報保護法によると、パスワード、生物情報、身分証明書などの個人情報は暗号化管理が必要である.
    暗号化は、個人情報が漏れたり、露出したりしても、その内容を確認するのが難しいセキュリティ技術です.
    方法ハッシュ(乱読)してDBに格納する.
    方法SSLを適用して暗号化する.(HTTPS)

  • パスワードが失われるたびにリセットされるのは、サーバが元のパスワードを調べられないためです.

  • 暗号化は復元が難しいため、ログイン時に入力したパスワードを暗号化してデータベースデータと比較します.
  • 2-2. いちほうこうハッシュかんすう


  • 本来ハッシュ関数は,資料をすばやく検索し,データの偽改ざんを調べるために用いられる.

  • 暗号学に用いられる一方向ハッシュ関数は復元できない.

  • SHA-256、(MD 5、SHA-1はセキュリティが悪い)など.

  • 最終的に暗号化されたテキストはDigestと呼ばれます.
  • ハッシュ関数とは?
  • 任意の長さのデータを固定長のデータの関数に返す.
  • 入力値の長さが異なり、出力値は常に固定長を返します.
  • 同じ値を入力すると、常に同じ出力値が保証されます.
  • ハッシュ関数は、暗号学ハッシュ関数と非暗号学ハッシュ関数に分けられる.
  • 2-3. 単一方向ハッシュの欠点と解決方法


  • ハッシュ関数の高速処理によりRainbow Table Attackに曝される可能性がある.
    →前処理のDigestが多く確保されており、Rainbow Tableを作成し比較できる.
  • Salting

  • パスワードでランダムに生成された文字列を復号します.
  • の比較を行うには、salt値とハッシュ値を一緒に保存する必要があります.
  • Key Stretching


    すなわち、
  • Salt値が追加された場合、複数回ハッシュが繰り返され、元の値の検索がより困難になる.
  • 2-4. bcrypt


    bcryptとは?


    salting&keystretchingの代表的なライブラリ
    多言語対応で使いやすい
    アルゴリズムタイプ、繰返し数、解法値、およびハッシュ値は、次のように最終ハッシュ値(Digest)に保存されます.

    bcryptの使用方法

  • bcryptライブラリ、importをインストールします.

  • 暗号化するpasswordおよびgensalt()を加えて復号化する.
  • password = "123dsaS!!"
    
    hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
    # TypeError("Unicode-objects must be encoded before hashing")
    
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    # 인코딩(바이트화)해야 암호화가 가능하다.
  • 暗号化されたhashed_passwordは、符号化状態のbytesタイプであり、decodeをデータベースに格納する.
  • hashed_password = hashed_password.decode('utf-8')
    
    # 다시 디코딩하여 string 타입으로 만든다.
  • で入力されたパスワードと暗号化されたパスワードが一致しているかどうかを比較します.
  • bcrypt.checkpw(input_password.encode('utf-8'), hashed_password.encode('utf-8'))
    
    # 인코딩된 상태로 함수에 넣어야 비교가 가능하다.
  • Pythonの文字列符号化
    文字コードは、ユーザが入力した文字または記号をコンピュータで使用可能な信号に変換し、Unicode文字列をUTF-8、ASCII、EUC-KRなどのバイト形式に変換するものである.
    Unicodeは国際標準文字表であり、UTF-8はUnicodeを用いた符号化方式である.
    Pythonの文字列はすべてUnicodeで、Python 2はASCIIを符号化し、Python 3はUTF-8を符号化する.
  • 3.トークンベースの認証システム


    3-1. 認証後の認証プロセス


  • 認証プロセス  access token  生成されます.このコインにはuser idなどプレイヤーを区別できる情報が含まれているはずですが、個人情報は含まれていません.

  • 認証されたユーザが要求を送信するとき  request headerAuthorizationの名義で. tokenメッセージ付き送信.

  • サーバはrequestのtoken情報を復号し、私たちが発行したtokenが正しいかどうかを確認し、useridなどの情報を検証します.

  • tokenから取得したユーザidを使用して、DBでそのユーザの権限(権限)を確認します.

  • ユーザーがリクエストの権限を持っている場合は、リクエストを処理します.

  • ユーザは、Unauthorized Response(401)または他のエラーコードを送信する権限を有しない.
  • 3-2. サーバまたはトークンベースの認証


    サーバベースの認証


    既存のネットワーク/モバイル認証システムは、サーバ側がユーザ情報を格納する方法である.このセッションの作成と維持には、セッションストレージ(メモリ、ディスク、データベースシステムなど)が必要です.
    ユーザ数が爆発的に増加すると、このようなサーバベースの認証は확장성 문제に遭遇する.
    分散サーバコンピュータを実行し、セッションを使用するには、非常に複雑なプロセスが必要です.
    CORSポリシー:Cross-Origin Resource Sharing
    ブラウザによる通信はCORSポリシーを採用し、他のドメインのリソース要求を制限します.
    Web上でセッション管理に使用される一般的なCookieも、単一ドメインおよびサブドメインでのみ動作するように設計されている.
    そのため、複数のドメインでCookieを管理するのも複雑で面倒です.

    トークンベースシステム


    認証時、サーバ側で生成されたトークンは、サーバ側ではなくクライアントに格納されます.
    したがって,サーバはログイン状態を覚える必要がなく,拡張サーバに理想的な環境である.
    すなわち、トークンベースシステムは、Stateless(ステータスなし)およびScalability(拡張性)を有する.
    拡張性(拡張性)
    トークンを使用したログイン情報は、より広範な分野で使用することができる.
    コインを発行するときは、選択的な権限でソーシャルログインできます.
    ex)KakaoTalkアカウントで登録されているサイトでは、KakaoTalk構成情報を取得できますが、KaoTalk情報は送信できません.
    トークンは、複数のデバイス互換性と複数のサービスをサポートするために使用できます.CORSポリシーについては、サーバ応答のタイトルセクションにAccess-Control-Allow-Originを追加する必要があります.

    4. JWT (JSON Web Token)


    4-1. JWTの動作原理

  • JWTは、認証に必要な情報を暗号化するトークンである.

  • 3.トークン発行:ユーザーの一意のID値とその他の情報をPayloadに入れて有効期間を設定する.
    →サーバ側のSECRET KEYで配布する.
    5.データ要求:サーバーに要求した場合、Access Token(JWT)をHTTPヘッダに送信する.
    6.トークン検証:トークンの署名をSECRET KEYに復号し、操作と有効期間を確認する.
    7.応答要求:検証が完了したら、Payloadを復号してユーザIDに適合するデータを取得する.

    4-2. JWT構造



  • 構造はHeader.Payload.Signatureからなる.
  • Header:トークンタイプ(typ)とハッシュアルゴリズム(alg)情報→符号化転送
  • Payload:公開/非公開クレーム(通常はユーザの一意のID値、有効期間)→符号化転送
  • Signature:JWTオリジナル確認→SECRET KEY暗号化を加えて転送
  • 4-3. JWTの使用方法(Pythonベース)

  • pyjwtライブラリ、jwtおよびimportをインストールします.

  • ユーザID、SECRET KEY、アルゴリズム情報を追加してトークンを発行する
  • SECRET_KEY = 'afsf34hjke1rh2j' # '랜덤한 조합의 키'
    
    access_token = jwt.encode({'id' : user.id}, SECRET_KEY, algorithm = 'HS256')
    
    print(access_token)
    'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MX0.-xXA0iKB4mVNvWLYFtt2xNiYkFpObF54J9lj2RwduAI'
  • トークンを受信して、ユーザが正しいかどうかを検証する(SECRET KEYを知る必要がある)
  • .
    header = jwt.decode(access_token, SECRET_KEY, algorithm = 'HS256')
    
    print(header)
    {'id': 1}      # 해당 유저가 맞는지 검증가능
    詳細なサンプルコードはInstargram Cloneプロジェクトで入手できます.

    4-4. JWTのメリットとデメリット


  • サーバは検証するだけで、追加のストレージは必要ありません.ステータスも拡張性もありません.(サーバの拡張、メンテナンス、メンテナンスが容易)

  • 拡張性が高く、ソーシャルログインのように他の認証システムにアクセスできます.

  • 逆に、一度発行したJWTは有効期限まで使えるので注意が必要です.
  • 既存Access Tokenの有効期間を短縮し、Refresh Tokenを再発行する.
    →以降学習Oauth2計画

  • 復号化さえすれば、誰でもWeb情報を知ることができるので、入力できる内容は限られています.

  • JWTの長さは、セッション/Cookie方式と比較して長い.サーバのリソースが浪費されます.
  • 参照リスト
  • 認定と承認
    トークンベースの認証の説明
    識別が容易なサーバ認証(セッション/Cookie、JWT)
    Pythonの文字コードについて