私のアプリケーションがvue-router
およびvuex
。次に、store
には、user
で始まるnull
オブジェクトが含まれます。ユーザーはサーバーから検証された後、ストア内のuser
オブジェクトに割り当てられたJWT
認証トークンを含むuser
オブジェクトを送り返します。ここで、ユーザーが3時間後に戻ってきて、ルートにアクセスしたり、他のアクションを実行しようとした場合、認証トークンの有効期限が切れていることを考慮して、それを確認する最良の方法は何でしょうか(axios post
をチェックして)ユーザーをlogin
ページにリダイレクトします。アプリには多数のコンポーネントがあるため、各コンポーネントのmounted
フックで有効なトークンをチェックするロジックを作成できることはわかっていますが、それはすべてのコンポーネントを繰り返すことを意味します。また、beforeEach
ナビゲーションガードを使用したくありません。checking...
またはloading...
。
グローバルミックスインを定義し、Vue.use(myMixin)
経由で使用できます。すべてのコンポーネントがこのミックスインを継承します。ミックスインでmounted
フックまたはおそらくactivated
フックを定義すると、すべてのコンポーネントで呼び出されます。
そこで、コンポーネントができることはすべて使用できます-this
はコンポーネントを指します。また、コンポーネントがフック自体も定義している場合、同じタイプのミックスインフックは、コンポーネントが所有するフックの前に実行されます。
少し異なるソリューションを使用しました。親index.htmlのルータービューの外部に存在する、ログイン関連のすべてを処理する単一のコンポーネントがあります。このコンポーネントは常にアクティブであり、div router-viewを非表示にして、読み込みメッセージまたはログイン画面をオーバーレイできます。イントラネットアプリケーションの場合、このコンポーネントはポーリングを使用して、ブラウザが開いている限りセッションを維持します。
このコンポーネントにルーターナビゲーションを読み込むことができます。 -そのため、ルーターナビゲーションをトリガーする子コンポーネントは、トップレベルの認証コンポーネントによって監視されるグローバルなリアクティブプロパティnavigateTo
を設定するだけです。これにより、認証チェック、場合によってはログインワークフローがトリガーされ、その後、トップレベルコンポーネントが$router.Push()
を呼び出します。このアプローチでは、ナビゲーションを完全に制御できます。
私は私のプロジェクトの1つで同様のことをします。実際にこれらのタイプの状況を処理するのは一見難しいですが、保護されたルートにbeforeEnter
ガードを追加し、認証が失敗した場合にリダイレクトすることができます。
const guard = function(to, from, next) {
// check for valid auth token
axios.get('/api/checkAuthToken').then(response => {
// Token is valid, so continue
next();
}).catch(error => {
// There was an error so redirect
window.location.href = "/login";
})
};
その後、あなたのルートで次のことができます:
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
guard(to, from, next);
}
},
あなたは私がlocation.href
のではなく router.Push
。ログインフォームがcsrfで保護されているため、新しいcsrf_tokenが必要です。
他の問題は、ユーザーがルートを変更せずにページを操作しようとした場合(つまり、ボタンをクリックして401応答を取得した場合)です。このため、各axios
リクエストで認証を確認し、401応答を受け取ったときにlogin
にリダイレクトするのが最も簡単です。
ガードチェック中にロードスピナーを追加するという点では、vuexストアにロードフラグを追加してから、ストアをルーターにインポートするだけです。正直なところ、私は気にしませんが、まともな実稼働サーバーでは、チェックが非常に迅速に行われるため、ユーザーはそれを見ることがほとんどありません。
vuex
を使用するため、isLoading
やisChecking
などの状態を追加できます。
そしてあなたのrouter.beforeEach
、現在のチェック状態に従ってisLoading
またはisChecking
を確認および設定できます。次に、この状態に従って読み込みメッセージを表示できます。
interceptors
を使用して、何らかのリクエストが発生したときに認証トークンをサイレントに取得できます。
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
const rToken = window.localStorage.getItem('rToken');
return axios.post('url/to/get/refresh/token', { rToken })
.then(({data}) => {
window.localStorage.setItem('token', data.token);
window.localStorage.setItem('rToken', data.refreshToken);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.token;
originalRequest.headers['Authorization'] = 'Bearer ' + data.token;
return axios(originalRequest);
});
}
return Promise.reject(error);
});