問題描述
- 基於乾坤qiankun微前端方案開發的系統,分為主系統和子系統兩部分,主系統包含系統管理、權限管理、子系統、注冊登錄、導航等模塊。子系統主要是某個自成體系的功能模塊。
- 本地開發主系統會調起登錄,登錄接口返回set-cookie(出於安全考慮會使用httponly模式),寫入到cookie中,對整個domain共享,后續的請求會寫攜帶上cookie,用於后端鑒權。
- 開發子系統的時候由於子系統不包含登錄,所以接口請求就會返回未鑒權。
- 此前的做法是,手動復制目標環境(代理接口的domain)的cookie到當前domain(即localhost)的cookie中,實現鑒權。
這樣做當然沒有問題,就是對於開發者看來說每次這樣復制一遍很是有辱斯文
, 畢竟寫代碼的初衷就是為了用技術替代重復的勞動
不是?
實踐思路
chrome插件
因為殼系統耦合了蠻重的業務邏輯,所以是想盡量在不動殼系統代碼的前提下解決問題。最近看了一點關於chrome開發的例子,想着用chrome插件完全解耦業務代碼,想想就覺得很棒。
最初的想法很簡單,通過腳本獲取到目標源的cookie,然后寫入到本地,完美?
事實上很快就被打臉了,接口通過responents setCookie的cookie,通過document.cookie()是獲取不到的!emoj?
那么,如果我在chrome插件中實現頁面嵌入iframe,iframe里面加載本地domain,然后用腳本更新目標地址的js,頁面刷新之后,這個cookike是不是就寫入到了本地domain了呢?我tm真是個人才!
再次被打臉,chrome的iframe也不是白給的,如果這么容易就被你盜用了其它網站的cookie,那豈不是cookie的安全策略成了擺設?
- 問題一是我修改了js文件之后,控制台會報“<”錯誤,我想應該就是解析出錯了吧;
- 其次就是全局的路由和vue實例已經掛在全局了,這個過程應該是不可逆的吧?
- 頁面刷新也是問題,直接
location.reload()
觸發更新,會重新加載本地文檔(src地址:localhost),腳本加上去的內容會被清除掉。涼涼,看來這又是死胡同。
回到原點
看來cookie的安全策略是繞不開的一座山。
干不掉的對手,就想辦法和它做朋友
從朋友那取了經,還是應該老老實實的把登錄從殼系統里面抽離出來,最好抽成獨立的模塊,生產npm包,子系統安裝成dev依賴,然后運行時判斷是否處在乾坤環境,選擇是否加載登錄頁面。
這里只講思路,具體實現起來並不復雜。
完成
設計思路
- 1、發送請求,返回當前登錄狀態
- 2、注入路由,/login
- 3、返回401:未認證--,跳轉到login
- 4、執行/login請求,刷新cookie
- 5、登陸成功,跳轉回默認頁或退出頁面
使用方式
發布到內網cnpm
- 安裝依賴
npm i qiankun-login --save-dev
- 在main.js or main.ts 中引入
import loggedInCheck from 'qiankun-login';
- 非乾坤環境下 Vue 實例化之后
if (!window.__POWERED_BY_QIANKUN__) {
const router = createVueRouter(routes);
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
// router 是vue-router實例化之后的對象
loggedInCheck(router);
}
router注入
const addRouter = router => {
const injectedLogin = router.getRoutes().some(e => e.path === "/login");
!injectedLogin && router.addRoute(route);
return router;
};
TODO
- 增加模板,包含殼系統的menu和頂部導航,皮膚切換等功能