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 のインストールと設定方法のグラフィック チュートリアル

推薦する

CSSカウンター関連属性の学習の詳細な説明

CSS カウンター属性はほぼすべてのブラウザ (IE8 を含む) でサポートされていますが、あまり使...

Docker はすべてのコンテナをバッチ起動して閉じます

Dockerの場合すべてのコンテナコマンドを開始する docker を起動します $(docker ...

CSS を使用して要素のスクロールバーを非表示にするサンプルコード

どの要素でもスクロールできるようにしながら、スクロールバーを非表示にするにはどうすればよいでしょうか...

JavaScript の instanceof メソッドの手動実装

1. instanceofの使用法instanceof演算子は、コンストラクター関数のprototy...

Linux または Android でファイル システムを追加する属性インターフェイスを解析する方法

最初のもの: 1. 主要なヘッダーファイルを追加します。 #include <linux/of...

XHTML 3つの文書型宣言

XHTML は 3 つのドキュメント タイプ宣言を定義します。最もよく使用されるのは XHTML T...

MySQLテクノロジーにおけるInnoDBロックの詳細な説明

目次序文1. ロックとは何ですか? 2. InnoDBストレージエンジンのロック2.1 ロックの種類...

Linuxシステムの操作レベルの詳細な紹介

目次1. Linuxシステムの操作レベルの概要2. 実行レベルを確認する3. 現在のシステムの動作レ...

MySQL インデックスがソートに与える影響の分析例

この記事では、例を使用して、MySQL インデックスがソートに与える影響を説明します。ご参考までに、...

mysql 3つのテーブルを接続してビューを作成する

3 つのテーブルが接続されています。テーブル A のフィールド a はテーブル B のフィールド b...

React Hooks に基づく小さな状態管理の詳細な説明

目次React Hooks に基づく状態共有の実装ユーザーエクスペリエンスこの記事では、主に Rea...

Nginx の高同時実行最適化の実践

1. チューニングの必要性​ 私は、どのように書けばいいのか本当に分からないので、共有するために最適...

MySQLの自動増分IDについて知っておくべきこと

はじめに: MySQL を使用してテーブルを作成する場合、通常は自動インクリメント フィールド (A...

SQLでEXPLAINコマンドを使用する方法

日常業務では、実行に時間のかかる SQL ステートメントを記録するために、スロー クエリを実行するこ...

Webpack でよく使われる 12 個の Loader を共有する (要約)

目次序文スタイルローダーCSSローダーsassローダーpostcssローダーバベルローダーtsローダ...