關鍵字:http-only
, cookie
,sessionid
, vue-router
, react-router
, 安全
,localStorage
, jwt
vue
需求描述
- 內部管理平臺,須要用戶登陸以後才能訪問。如今將 該平臺地址(www.xxx.com/home) 直接發給新來的運營同窗
- 前端須要檢測該用戶是否已登陸,若是未登陸,則將其 redirect 到登陸頁面
- 由於該頁面爲單頁應用,路由跳轉不涉及後端的 302 跳轉,使用前端路由跳轉
實現思路
實現代碼react
// 以 vue-router 爲例 // 登陸中間驗證,頁面須要登陸而沒有登陸的狀況直接跳轉登陸 router.beforeEach((to, from, next) => { const hasToken = document.cookie.includes('sessionid'); // 若是採用 jwt,則一樣 hasToken = localStorage.jwt const pathNeedAuth = to.matched.some(record => record.meta.requiresAuth); // 用戶本地沒有後端返回的 cookie 數據 && 前往的頁面須要權限 // if (pathNeedAuth && !hasToken ) { next({ path: '/login', query: { redirect: to.fullPath }, }); } else if (hasToken && to.name === 'login') { // 已登陸 && 前往登陸頁面, 則不被容許,會重定向到首頁 next({ path: '/', }); } else { next(); } });
- 應該在進入任何頁面以前,判斷:
- 該頁面是否須要權限才能訪問:登陸、註冊頁面不須要權限
- 用戶是否已經登陸:本地 cookie (或者 localStorage)包含 session 相關信息
Cookie: csrftoken=YaHb...; sessionid=v40ld3x....
- 若是
A頁面須要權限
且本地 cookie中包含了 sessionid 字段
,則容許訪問A頁面,不然跳轉到登陸頁面- 備註:sessionid 該字段由用戶在登陸以後,由後端框架經過
response.setCookie
寫入前端 ,所以該字段須要和後端同窗確認 - 須要後端同窗在 response header 中配置cookie中該字段的 http-only屬性,容許前端讀取 cookie。不然前端經過 document.cookie 讀取到的 cookie 將不包含 sessionid 字段
- 這個時候,可能會存在 js 讀取cookie 致使不安全的狀況,後端同窗能夠把 cookie 中的某個字段設置爲 容許讀取,其餘 cookie 設置不容許讀取,這樣即便被第三方不安全腳本獲取,也沒法產生負面影響。
- 備註:sessionid 該字段由用戶在登陸以後,由後端框架經過
- 若是
用戶已登陸
&& 在瀏覽器中輸入了登陸頁
地址,則將其重定向到首頁
更多說明
-
這樣作,前端就沒必要再向後端發起 API 作權限鑑定了(後端返回401,前端跳轉到 401),減小沒必要要的API 請求,特別是若是在API響應時間過長的狀況下,體驗不太友好。git
-
用戶修改 cookie,僞造 sessionidgithub
- 這樣的話,前端就無能爲力了,前端鑑權此時認爲該用戶合法。此時訪問首頁,將會調用獲取數據的API。
- 瀏覽器會將
用戶僞造的 sessionid
帶給後端,這時候就須要後端對 sessionid 進行較驗了。好比校驗前端帶來的 sessionid 與數據庫中的 sessionid 是否一致 - 用戶僞造的數據 sessionid 和 後端數據庫中 sessionid 的機率 很是很是低,能夠忽略不計,由於 sessionid 的位數通常在 32 位以上,由於裏面包含了字母和數字,也就由 32 ^ 36 種可能
- 結論:僞造沒有意義,即便用戶能夠看到頁面的樣子,可是看不到數據
-
採用 localStorage 而不是 sessionStorage 的緣由(SessionStorage 失效場景)vue-router
緣由:sessionStorage 沒法跨 Tab 共享數據庫
- 用戶在新打開一個 Tab,輸入已經登陸以後的某個頁面
- 經過
target="_blank"
來打開新頁面的時候,會致使會話失效 - 在當前頁面執行
Duplicate
(複製 Tab),sessionStorage 失效