DjangoRESTフレームワークのユーザー認証の基本

フロントエンドとバックエンドを分離したJWTユーザー認証

リソースはインターネットから提供されます
https://lion1ou.win/2017/01/18/

フロントエンドとリアエンドの認証
記事ディレクトリの分離

  1. 伝統的な方法
  2. Json Web Token(JWT)
    2.1。JWT構成
  3. JWTの使用
  4. IDとセッションストレージの違い
  5. 総括する

開発のためにフロントエンドとバックエンドが分離されているのに、なぜユーザー認証が必要なのですか?その理由は、HTTPプロトコルが状態(ステートレス)を保存しないためです。つまり、アカウントパスワードを使用してユーザーを認証すると、次の要求の直前にデータが忘れられます。したがって、私たちのプログラムは誰が誰であるかを知らないので、もう一度確認する必要があります。したがって、システムのセキュリティを確保するには、ユーザーがログインしているかどうかを確認する必要があります。

従来の方法では、
Restful APIを介したデータ対話のためにフロントエンドとバックエンドが分離されている場合、ユーザーのログイン情報とアクセス許可を確認する方法。元のプロジェクトでは、最も伝統的で単純な方法が使用されています。フロントエンドログイン、バックエンドはユーザー情報に基づいてトークンを生成し、トークンと対応するユーザーIDをデータベースまたはセッションに保存してから、トークンをユーザーに渡します。 、ブラウザのCookieに保存すると、ブラウザはこのCookieの取得を要求し、バックエンドはCookieの値に基づいてユーザーにクエリを実行し、有効期限が切れているかどうかを確認します。

しかし、これには多くの問題があります。ページにXSSの脆弱性がある場合、CookieはJavaScriptで読み取ることができるため、XSSの脆弱性によりユーザートークンがリークされ、ユーザーのIDを識別するバックエンドとして、Cookieの開示はユーザー情報がなくなったことを意味します。安全性。出力コンテンツをエスケープしたり、CDNを使用したりすることで、XSSインジェクションを回避できますが、大規模なプロジェクトでこの問題が発生しないことを保証することはできません。

Cookieを設定する場合、実際にはhttpOnlyとセキュアアイテムを設定できます。httpOnlyを設定すると、JSはCookieを読み取れなくなり、ブラウザが自動的にリクエストヘッダーに追加します。セキュアが設定されている場合、CookieはHTTPS経由でのみ送信されます。セキュアオプションは、HTTPプロトコルを使用する一部のXSSインジェクションを除外できますが、完全に防止することはできません。

httpOnlyオプションを使用すると、JSはCookieを読み取れなくなるため、基本的にXSSインジェクションについて心配する必要はありません。ただし、httpOnlyを設定すると、XSRFによって簡単に偽造されるという別の問題が発生します。つまり、クロスサイトリクエストです。このページをブラウザで開くと、別のページがサイト間でこのページのコンテンツを簡単にリクエストできます。デフォルトではCookieが送信されるためです。

さらに、認証情報がデータベースに保存されている場合、バックエンドは毎回トークンに基づいてユーザーIDを見つける必要があるため、データベースのクエリとストレージのオーバーヘッドが増加します。検証情報がセッションに保存されると、サーバー側のストレージ圧力が増加します。では、サーバーにクエリを実行することはできませんか?たとえば、対称暗号化アルゴリズムを使用してユーザーIDを暗号化してトークンを形成するなど、特定のルールに従ってトークンを生成する場合、サーバーはトークンを復号化することでユーザーIDが何であるかを実際に知ることができます。ただし、例を挙げます。これを行うと、対称暗号化アルゴリズムがリークされ、他の人がこの暗号化方法を使用してトークンを偽造できる限り、すべてのユーザー情報は安全ではなくなります。さて、非対称暗号化アルゴリズムでそれを行います。実際、これを行う仕様があります。これは、次に紹介するJWTです。

Json Web Token(JWT)

JWTはオープンスタンダード(RFC 7519)であり、通信する当事者間でJSONオブジェクトの形式で情報を安全に送信するための簡潔な自己完結型の方法を定義しています。JWTは、HMACアルゴリズムまたはRSA公開キーキーペアを使用して署名できます。これには2つの特徴があります。

  • コンパクト

データ量が少なく、伝送速度が速いため、URL、POSTパラメータ、またはHTTPヘッダーで送信できます。

  • 自己完結型

ロードにはすべてのユーザーが必要とする情報が含まれているため、データベースへの複数のクエリを回避できます

JWT構成

ここに写真の説明を挿入

ヘッダ

ヘッダーには、トークンタイプと使用される暗号化アルゴリズムの2つの部分が含まれています

{
    
    
  "alg": "HS256",
  "typ": "JWT"
}

Base64エンコーディングを使用してJWT構造の最初の部分を形成します。Node.jsを使用する場合は、Node.jsパッケージbase64urlを使用してこの文字列を取得できます。

Base64はエンコーディングです。つまり、元の外観に戻すことができます。これは暗号化プロセスではありません。

ペイロード

この部分は情報を保存する場所です。ここにユーザーIDやその他の情報を入力できます。この部分はJWT仕様でより詳細に紹介されています。一般的に使用されるのはiss(発行者)、exp(有効期限)、 sub(ユーザー向け)、aud(レシーバー)、iat(発行時間)。


{
    
    
    "iss": "qfedu.com",
    "iat": 1441593502,
    "exp": 1441594722,
    "aud": "www.example.com",
    "sub": "[email protected]"
}

同様に、Base64エンコーディングを使用してJWT構造の2番目の部分を形成します

署名

最初の2つの部分はすべてBase64を使用してエンコードされます。つまり、フロントエンドはロックを解除して内部の情報を知ることができます。署名では、エンコードされたヘッダーとペイロード、および提供されたキーを使用してから、ヘッダーで指定された署名アルゴリズム(HS256)を使用して署名する必要があります。署名の機能は、JWTが改ざんされていないことを確認することです。

3つの部分が接続されてJWTになっています。次のようになります。長さは、暗号化アルゴリズムと秘密鍵に関連しているようです。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

実際、この時点で、HTTP要求は常にトークンを運ぶので、トークンが渡されて不要な帯域幅を占有すると考える人もいるかもしれません。そう思うなら、HTTP2を理解することができます。HTTP2はヘッダーを圧縮します。これもこの問題を解決すると思います。

署名の目的
最終的な署名プロセスは、実際にはヘッダーとペイロードのコンテンツに署名して、コンテンツが改ざんされないようにすることです。誰かがヘッダーとペイロードの内容をデコード後に変更し、それをエンコードし、最後に前の署名の組み合わせを追加して新しいJWTを形成すると、サーバーは新しいヘッダーとペイロードによって形成された署名がJWTに添付されていると判断します。署名が異なります。新しいヘッダーとペイロードに署名する場合、サーバーの暗号化に使用されるキーがわからなくても、結果の署名も異なります。

情報公開
ここで誰もが質問する必要があります:Base64は一種のエンコーディングであり、リバーシブルです。その後、私の情報が公開されますか?

はい。したがって、JWTでは、機密データを負荷に追加しないでください。上記の例では、ユーザーのユーザーIDを送信しています。この値は実際には敏感ではなく、通常の状況では安全に知ることができます。ただし、パスワードなどのコンテンツをJWTに配置することはできません。ユーザーのパスワードをJWTに入力すると、悪意のあるサードパーティがBase64デコードを介してパスワードをすばやく知ることができます。

したがって、JWTは、機密性の低い情報をWebアプリケーションに配信するのに適しています。JWTは、ユーザー認証および承認システムの設計、さらにはWebアプリケーションのシングルサインオンの実装にもよく使用されます。

JWTの使用

ここに写真の説明を挿入
ここに写真の説明を挿入

まず、フロントエンドはユーザー名とパスワードをWebフォームを介してバックエンドインターフェイスに送信します。このプロセスは通常、HTTPPOSTリクエストです。推奨される方法は、SSL暗号化送信(httpsプロトコル)を使用して、機密情報が盗聴されるのを防ぐことです。
バックエンドはユーザー名とパスワードを正常にチェックした後、ユーザーのIDとその他の情報をJWTペイロード(ペイロード)として使用します。JWTペイロードはそれぞれBase64でエンコードされ、ヘッダーとスプライスされてJWTを形成します。結果のJWTは、lll.zzz.xxxに似た文字列です。
バックエンドは、フロントエンドへのログインが成功した結果としてJWT文字列を返します。フロントエンドは返された結果をlocalStorageまたはsessionStorageに保存でき、フロントエンドはログアウト時に保存されたJWTを削除できます。
フロントエンドは、要求するたびにJWTをHTTPヘッダーのAuthorizationビットに配置します。(XSSおよびXSRFの問題を解決します)
バックエンドは、それが存在するかどうかをチェックし、存在する場合は、JWTの有効性を検証します。たとえば、署名が正しいかどうか、トークンの有効期限が切れているかどうか、トークンの受信者が自分自身であるかどうかを確認します(オプション)。
検証に合格すると、バックエンドはJWTに含まれているユーザー情報を使用して他の論理操作を実行し、対応する結果を返します。セッションモードで
IDを保存する場合の違い
セッションモードでユーザーIDを保存する最大の欠点は、セッションがサーバー側に保存されるため、サーバーメモリを大量に消費し、大規模なアプリケーションでは多くの状態を保存する必要がある場合があることです。一般的に、大規模なアプリケーションでは、セッションストレージを実装するために、いくつかのKVデータベースと一連のキャッシュメカニズムを使用する必要もあります。

JWTメソッドは、ユーザーの状態をクライアントに分散します。これにより、サーバーのメモリ負荷を大幅に減らすことができます。ユーザーIDに加えて、ユーザーが管理者であるかどうか、ユーザーがいるグループなど、他のユーザー関連情報も保存できます。JWT方式では、サーバーに計算上のプレッシャー(暗号化、エンコード、デコードなど)がかかりますが、これらのプレッシャーはディスクストレージと比較して何もありません。それを使用するかどうかにかかわらず、さまざまなシナリオで話すためにデータを使用する必要があります。

シングルサインオン
セッション方式は、ユーザーIDを保存するために使用されます。最初は、ユーザーのセッションは1つのサーバーにのみ保存されます。複数のサブドメインを持つサイトの場合、各サブドメインは少なくとも1つの異なるサーバーに対応します(例:www.taobao.com、nv.taobao.com、nz.taobao.com、login.taobao.com)。したがって、login.taobao.comにログインした後でも、他のサブドメインでSessionを取得できることを認識したい場合は、複数のサーバーでSessionを同期する必要があります。ユーザーのステータスがクライアントに送信されているため、JWTを使用してもこの問題は発生しません。

まとめ
JWTの主な機能は次のとおりです。(1)ユーザー情報を添付でき、バックエンドはJWTを介して直接関連情報を取得します。(2)ローカルストレージを使用し、HTTPヘッダーのAuthorizationビットを介して検証のために送信します。しかし実際には、JWTがどこに保存されているかについて多くの議論があり、ローカルストレージに保存されていると言う人もいれば、Cookieに保存されていると言う人もいます。

おすすめ

転載: blog.csdn.net/qq_22648091/article/details/108540154