关键字: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 失效