Reduxを使ったトークン管理
背景
- Token(トークン)はユーザーのデータ識別子として、APIの権限管理において重要な役割を果たします。つまり、バックエンドでは多くのAPIが、現在のリクエストヘッダーにトークンデータが含まれているかどうかを確認し、正常にデータを返すかどうかを判断します。
- Tokenはユーザーの識別データとして、多くのモジュールで共有する必要があります。Reduxを使用することで、状態の共有問題を簡単に解決できます。
実装方法
- Redux内で、トークンを取得する非同期処理と、トークンを変更する同期処理を実装します。
- Loginコンポーネントがactionを送信し、フォームデータを渡す役割を担います。
code
- strore/modules/user.js
import { request } from '@/utils';
import {createSlice} from '@reduxjs/toolkit'
const userStore = createSlice({
name:'user',
initialState:{
token :''
},
reducers:{
setToken(state, action) {
state.token = action.payload
}
},
});
const fetchLogin = (loginForm) =>{
return async (dispatch)=>{
const res = await request.post('/v1_0/authorizations',loginForm)
dispatch(setToken(res.data.token))
}
}
const { setToken } = userStore.actions
const userReducer = userStore.reducer
export {setToken, fetchLogin}
export default userReducer;
- store/index.js
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './modules/user'
export default configureStore({
reducer: {
user: userReducer
}
})
- index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.scss';
import App from './App';
import { RouterProvider } from 'react-router-dom'
import router from './router'
import {Provider} from 'react-redux'
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store = {store}>
<RouterProvider router={router} />
</Provider>
</React.StrictMode>
);
以下是翻译成日文的内容:
トークンの永続化
課題
- Reduxにトークンを保存した後、ブラウザをリロードするとトークンが失われます。(永続化とは、リロード時にトークンが失われないようにすることです)
- Reduxはブラウザのメモリを利用したストレージ方式であるため、リロードすると状態が初期値に戻ります。
解決策
- トークンを取得した後、ReduxとlocalStorageの両方に保存します。
- トークンを初期化する際、まずlocalStorageにトークンが存在するか確認し、存在する場合はlocalStorageに保存されているトークンを使用して値を設定します。
APIのモジュール化
- トークンに関する各種操作は、プロジェクトの複数のモジュールで使用されるため、ツール関数としてカプセル化することで共有・再利用が可能です。
リクエストインターセプターによるトークンの注入
ルート認証
実装の考え方
- ローカルにトークンがあるか確認し、ある場合は子コンポーネントを返し、なければログインページ(Login)にリダイレクトします。
実装手順
-
components
ディレクトリにAuthRoute/index.jsx
ファイルを作成します。 - ログインしている場合、対応するページコンポーネントをレンダリングします。
- ログインしていない場合、ログインページにリダイレクトします。
- 認証が必要なページのルート設定を、
AuthRoute
コンポーネントを使ってレンダリングするように変更します。