API 認証に JWT を使用する Angular アプリは、API への呼び出しが返されたときにログイン ダイアログを起動し401 "Unauthorized"
、ユーザーが資格情報を入力して新しい有効な JWT を取得できるようにします。その後、アプリは失敗した無許可の要求を再試行し、フローを維持します。
ここにリストされているコードは、Chris Clarke によるこのソリューションに基づいています。
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(['$q', '$location', '$injector', function ($q, $location, $injector) {
return {
'responseError': function(response) {
// Keep the response waiting until we get new JWT
var deferred = $q.defer();
if (response.status === 401 && response.data.error && response.data.error.message.toLowerCase() === "unauthorized") {
// JWT has expired
// Open login dialog
var cslAuth = $injector.get('cslAuth');
if (cslAuth.isLoggedIn()) {
// Logout user, next pending request will not trigger auth dialog
cslAuth.logout();
$injector.get('ngDialog').openConfirm({
template: 'web_app/views/login.html',
className: 'ngdialog-theme-default',
showClose: false,
controller: 'LoginCtrl',
cache: false
})
.then(
function(value) {
// JWT has been refreshed. Try pending request again
var config = response.config;
// Inject the new token in the Auth header
config.headers.Authentication = cslAuth.getTokenHeader();
$injector.get("$http")(config).then(
function(response){
deferred.resolve(response);
},
function(response) {
deferred.reject();
}
);
},
function(value) {
deferred.reject();
}
);
}
} else {
return $q.reject(response);
}
// Return a promise while waiting for auth refresh
return deferred.promise;
}
}
}])
}])
問題は、期限切れのトークンを使用するリクエストが複数ある場合です。最初に戻ってくるものは、ログイン ダイアログをトリガーし、新しいトークンを取得する必要があります。しかし、新しいトークンが利用可能になるまで他の保留中の要求を待機させるにはどうすればよいでしょうか? 新しいトークンが要求されていることを後続のすべての受信応答に通知するフラグを設定できます。promise を返すことができ、すべての構成オブジェクトを Service の配列に格納できます。新しいトークンが利用可能になると、待機中のすべてのリクエストを再試行できます。しかし、新しいトークンが利用可能になった後に返される無許可のリクエストはどうなるでしょうか? それらは、新しいログイン ダイアログをトリガーします。
追加のメモ:
この回答は関連する問題の解決策を提供しますが、ここには新しいログインが含まれているため、このケースに解決策を適応させる方法がわかりません。
トークンを自動更新するオプションではありません。トークンの有効期限は 8 時間 (作業セッション) で、新しいログインが必須です。
- 構成オブジェクトにサービス (
cslAuth
およびここ)を挿入しても安全ですか?$http
私のコードは機能していますが、現時点では完全に準備ができていないことを読みました。