遇到此問題的背景:項目需要實現單點登錄,在前后端分離的前提下,前台如何保存token值成為了一個問題。想到的解決方案是,將token值統一存到一個前端程序,其他的前端程序去這個前端程序去取token(其他更好的解決方案歡迎指導~~)。在項目用angular的情況下,選擇了以下插件:angular-cross-storage,此插件可以實現跨域存取localStorage,操作非常簡單,都有demo。
通常情況下,設置HTTP的authorization只需在congfig中進行如下配置:
var app = angular.module("myApp",[]);
app.config(function($httpProvider) {
$httpProvider.defaults.headers.common["Authorization"] = 所需帶的權限;
});
但是在此處,權限值是存在另一個前端程序的token值,獲取權限token值是異步請求,並不能確定在何時能完成,說不定還沒得到token值,頁面已經發出了http請求,而這個沒設置Authorization的請求,勢必會返回401。
So 先要設置一個攔截器,並在攔截器里設置請求頭,代碼如下:
var app = angular.module("myApp",[ 'angular-cross-storage' ]); // 攔截器服務 app.factory("HttpInterceptor", function ($q, tokenService) { var HttpInterceptor = { request: function(config){ var deferred = $q.defer(); tokenService.getTokenEvents().then(function(res) { // 從另一個前端程序獲取token config.headers["Authorization"] = "bearer " + res.value; // 設置Authorization deferred.resolve(config); }).catch(function (err) { // do something... deferred.resolve(config); }); return deferred.promise; }, requestError: function(err){ return $q.reject(err); }, response: function(res){ console.log(res); return res; }, responseError: function(err){ if(-1 === err.status) { console.log(-1); // 遠程服務器無響應 } else if(500 === err.status) { // 處理各類自定義錯誤 } else if(401 === err.status) { } return $q.reject(err); } }; return HttpInterceptor; }
攔截器依賴一個對token操作的服務“tokenService", 代碼如下:
// token的存取及清除 app.factory("tokenService", function (CrossDomainStorage) { // CrossDomainStorage 是angular-cross-storage 的一個服務 var setToken = function (access_token) { return CrossDomainStorage.set("access_token",access_token) }; var setTokenType = function (token_type) { return CrossDomainStorage.set("token_type", token_type) }; var getToken = function () { return CrossDomainStorage.get('access_token') }; var clearToken = function () { return CrossDomainStorage.clear() }; return { setTokenEvents: function (access_token) { return setToken(access_token) }, setTokenTypeEvents: function (token_type) { return setTokenType(token_type) }, getTokenEvents: function () { return getToken(); }, clearTokenEvents: function () { return clearToken(); } } })
然后在config中配置攔截器, 代碼如下:
app.config(function ($httpProvider,CrossDomainStorageProvider) { $httpProvider.interceptors.push('HttpInterceptor'); })
就大功告成了,頁面發起的請求都會帶上 從另一前端程序取過來的 token值權限頭。