個人ブログのToken検証実践(ノードベース)
5281 ワード
前言なぜtoken を使うのか
HTTPは無状態のプロトコルであり,つまりHTTPはクライアントの情報を保存することができず,要求ごとの違いを区別することができない.
このようなシナリオを想定すると,AとBは同時に個人の文章を修正し,サーバは同時に2つのpostリクエストを受信するが,ブラウザはどのリクエストがAでどのリクエストがBであるかを知らず,一連の情報をマークし,リクエスト時に持参する識別子(token)が必要である. tokenとは何ですか Tokenは、クライアント要求のトークンとしてサーバが生成する一連の文字です.最初にログインすると、サーバはTonken文字列をクライアントに配布します.その後の要求では,クライアントがこのTokenを持参するだけで,サーバはそのユーザのアクセスであることを知ることができる.
個人的な理解は、サーバによって暗号化された個人情報の列です.例えば、次のようなものです.
サーバは、鍵を復号して現在のリクエスト者の情報を取得します.
テクノロジースタックフロントエンド:vue+ssr バックエンド:egg(nodeフレーム)+ts データベース:redis+mongo 導入:Docker 構築:Jenkins blogはほぼ完成し、ssrでレンダリングされました
本文は主にtoken検証について述べ,その他はもう述べない.
token設計の検証
私のblogはgetタイプの要求に対してtoken検証をしないで、その他資源の要求を修正することができます例えばPOST、PUTはtoken検証をします
以下の3つのステップに分解可能クライアントユーザはログインし、サービス側はユーザ情報に基づいてtokenを生成し、クライアント永続化ストレージ に格納.クライアント要求token サービス側はtokenを検証し、失敗すると直接エラー状態 に戻る.
1.フロントエンド(vue.js)
axiosライブラリを使用し、requestブロッキングでtokenをリクエストヘッダヘッダヘッダにプラグし、responseブロッキングでエラーステータスコードを一括してグローバルプロンプトします.
ログインに成功したらtokenをブラウザキャッシュに書き込み、リクエストごとに
フロントエンドキャッシュについては、ここではlocalForageライブラリをお勧めします.実用的です.
localForageはJavaScriptライブラリで、文字列だけでなく多くのタイプのデータを格納できます.localForageには優雅な降格ポリシーがあり、ブラウザがIndexedDBまたはWebSQLをサポートしていない場合はlocalStorageを使用します.
しかし、その操作は非同期で、自分でカプセル化して同期に変更することができます.
2.バックエンド(egg.js) token を生成する
ユーザーログイン、jsonwebtokenを使用してtokenを生成
jsonwebtokenの詳細はnode-jsonwebtokenをクリックしてください
暗号解読の使用も簡単で、secretが鍵であり、tokenの有効期限を設定できるUserServiceメソッドが直接与えられます.
ミドルウェアでtoken検証を行い、失敗したら直接返します.ミドルウェア検証 verifyミドルウェアをオンにし、特定のPOST要求のみを検証します.
オープンミドルウェア
verifyでcheckTokenメソッドを呼び出してtokenを検証する
これでtoken検証は終わりますが、不足があれば、ご指摘ください.
END
HTTPは無状態のプロトコルであり,つまりHTTPはクライアントの情報を保存することができず,要求ごとの違いを区別することができない.
このようなシナリオを想定すると,AとBは同時に個人の文章を修正し,サーバは同時に2つのpostリクエストを受信するが,ブラウザはどのリクエストがAでどのリクエストがBであるかを知らず,一連の情報をマークし,リクエスト時に持参する識別子(token)が必要である.
個人的な理解は、サーバによって暗号化された個人情報の列です.例えば、次のようなものです.
acess_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZWRhMTBjOTI0NThmNDAwMmFjZDEyMTAiLCJuaWNrX25hbWUiOiLlsI_osaoxOTk2IiwiY3JlYXRlZF90aW1lIjoiMjAyMC0wNi0wNVQwOTozMDo0OS42MThaIiwidXBkYXRlZF90aW1lIjoiMjAyMC0wNi0wNVQwOToyOToyMC4wNzlaIiwiaWF0IjoxNTkxMzQ5NDY4LCJleHAiOjE1OTE5NTQyNjh9.GmUJRXHed7M1xJyPaFFgaQKJoS-w8-l3N_PQFPiwwTE
サーバは、鍵を復号して現在のリクエスト者の情報を取得します.
テクノロジースタック
本文は主にtoken検証について述べ,その他はもう述べない.
token設計の検証
私のblogはgetタイプの要求に対してtoken検証をしないで、その他資源の要求を修正することができます例えばPOST、PUTはtoken検証をします
以下の3つのステップに分解可能
1.フロントエンド(vue.js)
axiosライブラリを使用し、requestブロッキングでtokenをリクエストヘッダヘッダヘッダにプラグし、responseブロッキングでエラーステータスコードを一括してグローバルプロンプトします.
ログインに成功したらtokenをブラウザキャッシュに書き込み、リクエストごとに
import Vue from 'vue';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
axios.interceptors.request.use(
async (config: AxiosRequestConfig) => {
const acess_token = await Vue.prototype.$getCacheData('acess_token'); # token
if (acess_token) {
config.headers.acess_token = acess_token;
}
return config;
},
(err: any) => Promise.reject(err),
);
axios.interceptors.response.use(
(response: AxiosResponse) => {
if (response.data.ret === 200) {
return response;
} else {
Vue.prototype.$global_fail(response.data.content);
return Promise.reject(response);
}
},
(err: any) => {
console.log(err);
if (err.code === 'ECONNABORTED' && err.message.indexOf('timeout') !== -1) {
Vue.prototype.$global_error(' , ');
}
if (err.response) {
Vue.prototype.$global_error(decodeURI(err.response.data.msg || err.response.data.message));
}
return Promise.reject(err);
},
);
フロントエンドキャッシュについては、ここではlocalForageライブラリをお勧めします.実用的です.
localForageはJavaScriptライブラリで、文字列だけでなく多くのタイプのデータを格納できます.localForageには優雅な降格ポリシーがあり、ブラウザがIndexedDBまたはWebSQLをサポートしていない場合はlocalStorageを使用します.
しかし、その操作は非同期で、自分でカプセル化して同期に変更することができます.
import Vue from 'vue';
import localForage from 'localforage';
Vue.prototype.$setCacheData = async (key: string, data: any): Promise => await localForage.setItem(key, data);
Vue.prototype.$getCacheData = async (key: string): Promise => await localForage.getItem(key) || null;
Vue.prototype.$clearCache = () => localForage.clear();
2.バックエンド(egg.js)
ユーザーログイン、jsonwebtokenを使用してtokenを生成
jsonwebtokenの詳細はnode-jsonwebtokenをクリックしてください
暗号解読の使用も簡単で、secretが鍵であり、tokenの有効期限を設定できるUserServiceメソッドが直接与えられます.
# /app/service/user.ts
import * as jwt from 'jsonwebtoken';
export default class UserService extends Service {
private secret = 'Hello__World'; #
async createToken(user: User): Promise {
const payload = {
_id: user._id,
nick_name: user.nick_name,
created_time: user.created_time,
updated_time: user.updated_time,
};
return jwt.sign(payload, this.secret, { expiresIn: '7d' }); #
}
checkToken(token: string): User {
try {
# token
return jwt.verify(token, this.secret);
} catch (e) {
throw ' token';
}
}
}
ミドルウェアでtoken検証を行い、失敗したら直接返します.
オープンミドルウェア
# /config/config.default.ts
config.middleware = ['verify'];
config.verify = {
enable: true,
# POST
match(ctx) {
return ctx.request.method === 'POST';
},
};
verifyでcheckTokenメソッドを呼び出してtokenを検証する
# /app/middleware/verify.ts
module.exports = () => {
return async (ctx, next) => {
if (ctx.path.startsWith('/api/user/login') || ctx.path.startsWith('/api/user/sendCode') || ctx.path.startsWith('/api/user/register')) {
return await next();
}
try {
const acess_token: string = ctx.request.header.acess_token;
if (!acess_token) {
throw ' ';
} else {
await ctx.service.user.checkToken(acess_token); # token
return await next();
}
} catch (e) {
# token ,
console.log(e);
ctx.body = {
ret: 304,
content: `${e}`,
};
}
};
};
これでtoken検証は終わりますが、不足があれば、ご指摘ください.
END