Nodeはkoa2を使用してシンプルなJWT認証方式を実装します

Nodeはkoa2を使用してシンプルなJWT認証方式を実装します

JWT の紹介

JWTとは

正式名称はJSON Web Tokenで、現在最も人気のあるクロスドメイン認証ソリューションです。基本的な実装は、サーバーが認証した後、 JSONオブジェクトを生成し、それをユーザーに送り返すことです。ユーザーがサーバーと通信する場合、このJSONオブジェクトを送り返す必要があります。

JSON次のようになります。

{
 「名前」:「張三」、
 「役割」: 「管理者」、
 「有効期限」: 「2018年7月1日 00:00」
}

JWT が必要な理由は何ですか?

まず、 session_idCookie実装に基づいた一般的な認証プロセスを見てみましょう。

1. ユーザーはユーザー名とパスワードをサーバーに送信します。

2. サーバー検証に合格すると、ユーザーロール、ログイン時間などの関連データが現在のsessionに保存されます。

3. サーバーはユーザーにsession_idを返し、それをユーザーのCookieに書き込みます。

4. ユーザーによる後続の各リクエストでは、 session_idCookieを通じてサーバーに返されます。

5. サーバーはsession_idを受信し、以前に保存されたデータを検索して、ユーザーの ID を認識します。

しかし、ここで大きな問題があります。サーバー クラスターの場合、セッション データの共有が必要になり、各サーバーがセッションを読み取ることができます。この実装のコストは比較的高くなります。

JWT考え方を変え、 JSONデータをフロントエンドに返します。フロントエンドが再度リクエストすると、検証のためにデータがバックエンドに送信されます。つまり、サーバーはステートレスなので、拡張が容易になります。

JWT データ構造

JWTの 3 つの部分は次のとおりです。

Header 、次のようなもの

{
 "アルゴリズム": "HS256",
 "タイプ": "JWT"
}

alg属性は署名アルゴリズム ( algorithm ) を示し、デフォルトはHMAC SHA256 ( HS256と表記) です。 typ属性はtokentype JWT示します。JWT トークンはJWT

Payload 。これはJSONでもあり、送信する必要がある実際のデータを保存するために使用されます。 JWT 7 つの公式フィールドを指定します。下記の通り

  • iss (発行者): 発行者
  • exp (有効期限): 有効期限
  • sub (件名): 主題
  • aud (観客): 観客
  • nbf (Not Before): 有効時間
  • iat (発行日時): 発行時刻
  • jti (JWT ID): ID

もちろん、プライベートフィールドをカスタマイズすることもできます。 ただし、JWT はデフォルトでは暗号化されておらず、誰でも読み取ることができるため、この部分には秘密情報を入れないでください。

SignatureSignature部分は、データの改ざんを防ぐための最初の 2 つの部分の署名です。まず、 secret )を指定する必要があります。このキーはサーバーのみが知っており、ユーザーには公開できません。次に、 Headerで指定された署名アルゴリズム(デフォルトはHMAC SHA256 )を使用して、次の式に従って署名を生成します。

HMACSHA256
 base64UrlEncode(ヘッダー) + "." +
 base64UrlEncode(ペイロード)、
 秘密)

署名を計算した後、 HeaderPayloadSignatureの 3 つの部分が文字列に結合され、各部分が「ドット」(.) で区切られて、ユーザーに返されます。下記の通り

JWTのセキュリティ

  • JWTデフォルトでは暗号化されませんが、暗号化することは可能です。秘密データはJWTなしではJWTに書き込めません
  • JWT自体には認証情報が含まれており、漏洩すると誰でもトークンのすべての権限を取得できるようになります。盗難を減らすには、 JWTの有効期間を短く設定する必要があります。いくつかの重要な権限については、使用時にユーザーを再度認証する必要があります。
  • 盗難を減らすために、 JWT HTTPプロトコルを使用してプレーンテキストで送信するのではなく、 HTTPSプロトコルを使用して送信する必要があります。

Node の簡単なデモ - Koa JWT の実装

理論的な知識について説明した後、 JWT実装する方法を見てみましょう。一般的なプロセスは次のとおりです。

まず、ユーザーがログインすると、サーバーはユーザー情報に基づいてtokenを生成し、クライアントに返します。フロントエンドは、次のリクエストでtokenをサーバーに渡します。サーバーはトークンが有効であることを確認した後、データを返します。無効な場合は401ステータスコードを返す

ここではNodeを使って実装します。使用する主なライブラリは次の2つです。

jsonwebtoken は、 tokenの生成、検証などを行うことができます。

Koa-jwtミドルウェアは、主にtoken検証に使用されるjsonwebtokenさらにカプセル化します。

koaプロジェクトを素早く構築する

現時点では、 Vue-cliのようにkoaプロジェクトをすばやくビルドする公式の方法は存在しないことがわかりました。 ( koaプロジェクトの構築コストも低いのかもしれません)。しかし私は怠け者なので、比較的使いやすいツール、koa-generatorを見つけました。

インストール

npm をインストール -g koa-generator

koa2 my-project my-projectという新しいkoa2プロジェクトを作成します。

cd my-projectnpm install

プロジェクトを開始するnpm start

localhost:3000開く

トークンを生成する

デモンストレーションの便宜上、実際にはデータベースに保存されるユーザー情報を格納するための変数userList直接定義します。

const crypto = require("crypto"),
 jwt = require("jsonwebtoken");
// TODO: データベースを使用する // これはデータベースに保存する必要がありますが、これはデモンストレーション用です let userList = [];

クラスUserController {
 // ユーザーログイン static async login(ctx) {
  const データ = ctx.request.body;
  if (!data.name || !data.password) {
   ctx.body = {を返します
    コード: "000002", 
    メッセージ: 「無効なパラメータ」
   }
  }
  const result = userList.find(item => item.name === data.name && item.password === crypto.createHash('md5').update(data.password).digest('hex'))
  if (結果) {
   const トークン = jwt.sign(
    {
     名前: 結果.名前
    },
    "Gopal_token", // シークレット
    { expiresIn: 60 * 60 } // 60 * 60 秒
   );
   ctx.body = {を返します
    コード: "0",
    メッセージ: 「ログイン成功」、
    データ: {
     トークン
    }
   };
  } それ以外 {
   ctx.body = {を返します
    コード: "000002",
    メッセージ: 「ユーザー名またはパスワードが正しくありません」
   };
  }
 }
}

モジュールをエクスポートします。

jsonwebtokensignメソッドを使用してtokenを生成します。このメソッドの最初のパラメータはPayloadを参照します。これは、エンコード後にtokenに格納されるデータです。また、 tokenを検証した後に取得できるデータでもあります。 2 つ目は、サーバー固有の秘密鍵です。検証中にデコードするには、これらが同じである必要があり、秘密に保持されることに注意してください。一般的に、パブリック変数を定義するのが最適です。ここでは、デモンストレーションの便宜上、直接ハードコードされています。 3番目のパラメータはoptionで、 token有効期限を定義できます。

クライアントがトークンを取得する

フロントエンドがログインしてtokenを取得した後、それをcookieまたはlocalStorageに保存できます。ここではlocalStorageに直接保存します

ログイン() {
 これ.$axios
  .post("/api/ログイン", {
   ...このルールフォーム、
  })
  .then(res => {
   (res.code === "0"の場合){
    this.$message.success('ログインに成功しました');
    localStorage.setItem("トークン", res.data.token);
    this.$router.push("/");
   } それ以外 {
    this.$message(res.message);
   }
  });
}

axiosインターセプターをカプセル化し、リクエストが行われるたびに、リクエスト ヘッダーで検証のためにtokenサーバーに送信します。事前にCookieに配置しておけば自動的に送信できますが、クロスドメインにはできません。したがって、推奨される方法は、HTTP リクエスト ヘッダーAuthorizationに配置することです。ここでのAuthorization設定に注意し、先頭にBearerを追加します。詳細については、ベアラー認証を参照してください。

// axios リクエストインターセプターはリクエストデータを処理します axios.interceptors.request.use(config => {
 const トークン = localStorage.getItem('トークン');
 config.headers.common['Authorization'] = 'Bearer ' + token; // ここで Authorization に注意してください
 設定を返します。
})

トークンを確認する

検証にkoa-jwtミドルウェアを使用するのは、以下に示すように比較的簡単です。

// エラー処理 app.use((ctx, next) => {
 戻り値 next().catch((err) => {
   (エラーステータス === 401)の場合{
     ctx.ステータス = 401;
    ctx.body = '保護されたリソース。アクセスするには Authorization ヘッダーを使用します\n';
   }それ以外{
     エラーをスローします。
   }
 })
})

// 注: ルートの前に配置します app.use(koajwt({
 シークレット: 'Gopal_token'
}).unless({ // ホワイトリストのパスを設定する: [/\/api\/register/, /\/api\/login/]
}))

// ルート
app.use(index.routes(), index.allowedMethods())
app.use(users.routes()、users.allowedMethods()) を使用します

以下の点に注意することが重要です。

  • secret sign時と同じである必要があります
  • ログイン/登録など、検証する必要のないURLを指定するインターフェースのホワイトリストは、 unlessを通じて設定できます。
  • 検証ミドルウェアは、検証が必要なルートの前に配置する必要があります。 前述のURL検証できません。

デモ

ログインが必要なインターフェースに直接アクセスすると、 401が発生します。

最初に登録してからログインしてください。そうしないと、ユーザー名またはパスワードが間違っているというメッセージが表示されます。

ログイン後、 Authorizationを行うと正常にアクセスでき、 200返してデータを修正できます。

要約する

この記事では、 JWT認証に関する知識をまとめ、 koa2で実装した簡単なdemoを紹介します。皆様のお役に立てれば幸いです。

記事が長くなったので、比較的簡単なkoa-jwtのソースコードについて個別にお話しする機会がありました〜

この記事のdemoアドレス: クライアントとサーバー

参照する

JSON Web Token 入門チュートリアル

Node.js アプリケーション: Koa2 は認証に JWT を使用します

Node で koa2 を使用して簡単な JWT 認証方式を実装する方法についての記事はこれで終わりです。Node koa2 JWT 認証に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Node.js Koa2 が認証に JWT を使用する例

<<:  Trash-Cli: Linux のコマンドラインごみ箱ツール

>>:  Windows 10 での MySQL 5.7.17 のインストールと設定方法のグラフィック チュートリアル

推薦する

Linux で特定のプログラムを見つけるための whereis の例の詳細な説明

Linuxは特定のプログラムを見つけますwhereis コマンドは主にプログラム ファイルを検索し、...

表の境界線の CSS 構文

<br />表の境界線の CSS 構文具体的な内容には、上境界線の幅、右境界線の幅、下境...

CentOS6.7 mysql5.6.33 でデータファイルの場所を変更する方法

問題: MySQL がデータ ファイルを保存するパーティションの容量が小さく、現在いっぱいになってい...

CSS の overflow: hidden の使い方 (オーバーフローの非表示とフロートのクリア)

オーバーフロー非表示指定された高さを超えるテキストや画像情報を非表示にすることを意味します。 <...

Docker コンテナで ASP.NET Core を実行する手順

最近は学ぶべき知識が多すぎて、どれを先に学べばいいのかわかりません。このブログはもともとxamari...

TSで最も一般的な宣言マージ(インターフェースマージ)

目次1. マージインターフェース1.1 非関数メンバー1.2 関数メンバー序文:今日お話ししたいのは...

Centos7 での Mysql5.7.19 の詳細なインストールチュートリアル

1. ダウンロード公式サイトからmysql-5.7.19-linux-glibc2.12-x86_6...

Zabbix ベースの Jenkins プロセス監視の詳細な説明

1. 監視アーキテクチャ図 2. 実装のアイデアJenkins に Metrics プラグインをイン...

サーバーストレステストの概念と方法 (TPS/同時実行性)

目次1 ストレステストの指標1.1 秒あたり1.2 クォータ1.3 平均処理時間(RT) 1.4 同...

VueとReactの詳細

目次1. パノラマII. 背景1. 反応: プロフェッショナル2. ビュー: 凡例3. 技術的な思考...

Window.nameはクロスドメインデータ転送の問題を解決します

<br />原文: http://research.microsoft.com/~hel...

フロートとBFCをクリアするCSSメソッド

イギリスBFC: ブロック書式設定コンテキストBFCレイアウトルール内箱は縦方向に次々に配置されます...

MySql のグループ化と各グループからランダムに 1 つのデータを取得する

アイデア: 最初にランダムに並べ替えてからグループ化します。 1. テーブルを作成します。 テーブル...

JavaScriptは組み込みオブジェクトのプロトタイプメソッド実装を追加します

オブジェクトがメソッドを呼び出す順序:インスタンス内にメソッドが存在しない場合は、インスタンス オブ...

CSSは親要素の下の最初の子要素を選択します(:first-child)

序文最近、プロジェクトで :first-child を使用したのですが、すぐに思いつきました。これは...