アンギュラJWTトークン認証
デモhttps://gitee.com/powersky/jwt
入門
ウェブトークンJSON(JWT)に基づいて、ネットワークアプリケーション実行環境の間を通過するために、文ですJSON、オープンスタンダード((RFC 7519)。トークンは、特にシングル分散サイトのため、コンパクトで安全であるように設計されてサインオン(SSO)シナリオ.JWT文は一般的に提供するために使用されており、サービスプロバイダは、サーバからリソースを取得するために識別情報を認証されたユーザ識別情報との間で転送し、あなたもでなければならないいくつかの余分な他のビジネス・ロジックを追加することができます、ステートメント情報トークンは直接認証に使用することができますが、暗号化することができます。
起源
スピーキングでJWTを前に基づいて話に必ずトークンとセッション異なります。
伝統的なセッション認証
HTTPプロトコル自体は、httpによると、ので、ユーザーは次回の要求、その後、ユーザー認証のために私たちのアプリケーションにユーザー名とパスワードを提供する場合、ユーザーはジョブのユーザー認証のために再度必要があることを意味し、ステートレスなプロトコルであります、我々はリクエストが送信されたユーザーを知ることができないので、私たちのアプリケーションは要求が発行された利用者を識別できるようにするために、我々は唯一のユーザーに関する情報を格納することができます契約がサーバーに記録され、このログイン情報は、に応じて渡されますブラウザに、保存するためにそれを教えてくれたクッキーを、次回は、アプリケーションが我々のアプリケーションからユーザーの要求を識別することができるようになりますように、私たちの要求に送信され、これは伝統的に基づいているように、セッション認証。
しかし、このベースのセッションアプリケーション自体が異なるクライアントのユーザーの増加とともに、拡大することは困難であるように、認証、サーバーとは独立しては、より多くのユーザーを運ぶことができないが、今回はベースのセッション問題認定アプリケーションが公開されます。
ワークス
場合は、クライアントのユーザー名、パスワード要求サーバーと認証を通過し、サーバーは認証関連の生成セッションデータをとメモリまたはメモリデータベースに格納されています。そして、対応sesssion_id
への復帰のクライアントを、クライアントが保存されますsession_id
(署名が改ざんを防止するために暗号化することができます下)でクッキー。後は、クライアントすべての要求はこれに含まれますsession_id
決定するために、(すべての後に、デフォルトのクッキーがサーバを通過します)サーバーの存在または不在に対応するセッションデータを、ログイン状態を確認し、持っているために何の権限、そうでない場合は、なぜなぜの敬意を検証することであれば、再度ログインします。
フロントの出口は、その後、クリアするためにクッキーを。強制再認証または修飾の前端部の後端部は、クリアするセッション。
長所と短所
長所:
- JWTと比較し、最大の利点は、あなたがセッションをクリアするためのイニシアチブをとることができるということです。
- セッションはサーバー側に保存され、彼らは比較的安全です。
- クッキーの使用、より柔軟に、より優れた互換性を兼ね備えています。
短所:
-
私たちの適用後の各ユーザ認証は、サーバー上の私たちのアプリケーションがユーザーの次のリクエストの識別を容易にするために、記録を行う必要があり、一般的なセッションがメモリに格納され、認証されたユーザの増加とされ、サーバーのコストが大幅に増加します。
-
認証されたレコードはメモリに保存されている場合は、ユーザ認証後、認証記録を行うサーバは、その後、次回、ユーザーの要求にも許可を取得するように、このサーバ上のリソースを要求する必要があることを、この手段は、その分散しますアプリケーションに対応するには、ロード・バランサの能力を制限します。アプリケーションのスケーラビリティを制限これも手段。
分散展開では、共有セッションメカニズムに複数のマシンを実行する必要があり、セッションの方法は、データベースまたはRedisの中に保存することができます
-
それは、ユーザを識別するために、クッキーに基づいているため、クッキーが傍受された場合にCSRFに簡単には、ユーザーは、クロスサイトリクエストフォージェリ攻撃に対して脆弱である可能性があります。
-
シーン間でのCookie +セッションが良くありませんでした
差分セッション、クッキー、のsessionStorage、ののlocalStorage
セッション:
サーバー側の主ストア、比較的安全。
クッキー:
有効時間を設定することができ、デフォルトでは、ストアサイズは4キロバイト程度で、障害発生後にクライアントの主記憶装置を、ブラウザを閉じて、非常に安全ではないことです。
sessionStorage:
現在のセッションで、ブラウザページを閉じるか、または除去した後にのみ有効です。
ローカルストレージ:
クリア、そうでない場合は永久保存しない限り。
JWTトークンベースの認証メカニズム
JWT三つの部分、即ちによって分離本質的に「」頭、ペイロードと署名。簡単なJWTの例は、次の通り:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOjEsImlhdCI6MTU4MTMyMjE4MCwiZXhwIjoxNTgxMzI5MzgwfQ.6PVma3dLCbiXYgBJld5McFJ-q-QydCY7YVtrKPBsRi8
列のこの部分は、実際には3つの部分、符号分割の使用の焦点から構成され、JWTは:で表すヘッダ、ペイロード、署名。
ヘッダ
JWT ヘッダー:典型的には二つのフィールド、すなわち、含む標準(タイプ)とALG(アルゴリズム)。
- 標準:トークン型は、そこに固定されているJWT。
- ALGは:暗号化アルゴリズムは、一般的に直接使用します
HMAC
SHA256
。
完全なヘッド次の文:
{
'typ': 'JWT',
'alg': 'HS256'
}
その後、ヘッドbase64で暗号化は、(暗号化は、対称復号化することができる)、第1の部分を構成しています。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Playload
ロードは有効な情報は、以下の三つの部分が含まれている有効な情報を格納する場所です。
- 標準的な登録届出書
- 公式声明
- Privateステートメント
標準的な登録届出書
- ISS:JWTの発行者
- サブ:ユーザーのためのJWT
- AUD:受信側JWT
- EXP:JWT有効期限、有効期限は、時間の問題よりも大きくなければなりません。
- NBF:前に定義されて何時間JWTは使用できません。
- IAT:時間の問題JWT
- JTI:JWT独自のアイデンティティは、主にリプレイ攻撃を避けるために、ワンタイムトークンとして使用されています。
タイムスタンプは、一般的に示し、UNIXタイムスタンプを使用しています。
公式声明
公共の宣言は、必要な情報やその他のビジネスニーズを追加するために、ユーザーに関する一般的な情報を任意の情報を追加することができますが、クライアントの一部を復号化することができるため、機密情報を追加することはお勧めしません。
Privateステートメント
Privateステートメントは、共通の定義としての文の提供者と消費者であるため、一般的に、機密情報を保存することは推奨されませんBASE64は、情報の一部が平文として分類することができることを意味し、対称復号化されます。
簡単な定義ペイロードを次のように、:
{
userID: '1',
exp: '1581329380',
iat: '1581322180'
}
次いで施さbase64で暗号化が得JWT第2の部分を。
eyJ1c2VySUQiOjEsImlhdCI6MTU4MTMyMjE4MCwiZXhwIjoxNTgxMzI5MzgwfQ
オンライン変換ツールBASE64 アドレス。
署名
JWT第三の部分はビザ情報であり、このビザ情報は、3つの部分からなります:
- (暗号化されたBASE64後)ヘッダ
- ペイロード(BASE64後に暗号化されました)
- 秘密
この部分は、必要base64で暗号化されたヘッダとbase64で暗号化されたペイロードストリング接続を使用して、次に、提供されるヘッダの暗号化のためと宣言された秘密の暗号化の組み合わせを、次いで構成JWT第三の部分を。
例えば:
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');
秘密がサーバ側に保存されている、JWTは発行され、サーバー側で生成された秘密が使用されJWTが発行され、JWTのように、それはあなたのサーバの秘密鍵であり、検証、あらゆるシーンに明らかにすべきではありません。クライアントが学習した後は秘密を、それはクライアントが自己署名できることを意味しJWTその後、あなたのプログラムは、おそらく攻撃を雇うだろう、。
長所と短所
利点:
- そのためJWTは、JAVA、JavaScriptを、NodeJS、PHPおよび他の多くの言語と同様に、クロス言語サポートできるように、JSONの汎用性を使用することができます。
- ペイロード部のなので、あなたはそれ自体が非機密情報のために必要ないくつかのJWT他のビジネス・ロジックを格納することができます。
- それは非常に簡単に輸送することであるので、輸送の容易さは、JWTの構成は、小さな占有バイト非常に簡単です。
- アプリケーションを拡張することは容易であるので、それは、サーバー上のセッション情報は保存されません。
短所:
- トークンの設計上の問題を更新する必要があります
- トークンがまだ有効な問題であるユーザー出口を設計する必要があります
- まだ有効であるトークンパスワード変更に関する問題の後
- そこの小さな多くの問題がありますが、私はそれが害よりも良いと思います
申し込み方法
これは、一般的に、要求にあらかじめ追加されAuthorization
、そして追加Bearer
のラベルを:
fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
作品のように:
角度は、JWTを認証するために使用します
ここでデモを使用する例をTODO。
APIデザイン
/auth
POSTは、ユーザー名提出username
とパスワードをpassword
ログイン認証、返品にJWTの文字列。/todos
GETは、to-doリストを返します。/todos/{id}
GETは、指定されたバックログを返します。/users
GETは、ユーザーのリストを返します。
簡単なプログラムの動作フロー
最初のプログラムは、ログイン画面、入力されたユーザ名とパスワードにユーザーのニーズを持っています。フォームが送信される場合には、後端の先端にデータを送信する/auth
経路。適切なバックエンドクエリに成功した復帰後の検証のため、ユーザーは、検証取るトークン文字列を。
バックエンドのデータ宣言
// 定义用户
const USERS = [
{ id: 1, username: 'vincent', password: '123456'},
{ id: 2, username: 'bob', password: '123456'},
{ id: 3, username: 'peter', password: '123456'},
];
// 创建TODO列表,json格式
const TODOS = [
{ id: 1, userId: 1, name: "Play LOL", completed: false },
{ id: 2, userId: 1, name: "Do homework", completed: true },
{ id: 3, userId: 2, name: "Play basketball", completed: false },
{ id: 4, userId: 3, name: "Finish Angular JWT", completed: false },
];
パスワードを覚えて配置することができないペイロードを、それは安全ではないので、で。
バックエンドのコードの実装
-
インポートライブラリが必要
const _ = require('lodash'); const express = require('express') const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const expressJwt = require('express-jwt');
-
定義関数
// 获取用户相关的所有Todo事项函数 function getTodos(userID) { var todos = _.filter(TODOS, ['userId', userID]); return todos; } // 获取指定id的todo事项 function getTodo(todoID) { var todo = _.find(TODOS, (todo) => { return todo.id == todoID; }) return todo; } // 获取所有用户 function getUsers() { let users = Array(USERS.length); for (let i = 0; i < USERS.length; i++) { users[i] = {id: USERS[i].id, username: USERS[i].username}; } return users; }
-
使用して、
expressJwt
生成したトークンtodo-shared-secret
秘密鍵は注意がバックエンドに格納されなければならないことを、文字列です。
具体的なコードはここにhttps://gitee.com/powersky/jwtに来ることができます。 -
他のAPIを実装
フロントエンドのコードの実装
フロントエンドは、次のセクションに分かれています。
サービス:
user service
ユーザデータを取得するために使用todo service
データTODOを取得しますauth service
トークンは、アクセスに認証ユーザーに使用しましたauth guard
ルートを守るため、ルートはスキップか否かを判定することができます
コンポーネント:
user list
ユーザーインターフェイスの表示todo list
ユーザインタフェース表示のTODO TODOlogin
ユーザーログインインターフェイス
以下示すために。
-
user.service.ts
-
todo.service.ts
-
auth.service.ts
-
auth.guard.ts
-
UserListComponent
とhtml
-
TodoListComponent
とhtml
-
LoginComponent
とhtml
-
AppComponent
とhtml
-
AppRoutingModule
コンフィギュレーション・ファイルを追加するには、プロキシの必要性を使用できるようにするには:
proxy.conf.json
{
"/api/*": {
"target": "http://localhost:4000",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
}
そして、package.json
コメントを追加しました:
"name": "jwt",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
そして、フロントエンドを有効にするには、次のコマンドラインコマンドを実行します。
npm start
バックエンドを起動するには、次のコマンドを実行します。
node server/app.js
このこの場合はオーバーです。