1.当前我的工作触及到的后台项目,在前端的登陆部分有所需求,相信每一个项目都会有登陆模块,而提到登陆,我一直都是云里雾里,只是浅浅的了解一些,比如我对于登陆部分的了解就停留在边角料阶段:
在登录页点击登录的时候,前端会带着用户名和密码去调用后端的登录接口后端收到请求,验证用户名和密码,若验证失败,返回错误信息,前端提示相应的错误信息。如果验证成功,就会给前端返回一个token前端拿到token,将token存储到vuex和localStorage中,并跳转页面,即登录成功,前端每次跳转至需要具备登录状态页面时,都需要判断当前token是否存在,不存在就跳转到登录页,存在则正常跳转(通常封装在路由守卫中)最后,前端在向后端发送其他请求的时候,需要在请求头中带上token(项目中通常封装在请求拦截器中),后端判断请求头中有无token,有则验证该token,验证成功就正常返回数据,验证失败(如已过期)则返回相应错误码。前端拿到错误信息,清除token并回退至登录页。而这样的一个流程也只是泛泛的皮毛,登陆之复杂,也是在了解之后才清楚。
2. 前后端分离的项目登陆模块我了解的是有四种:第一种是Cookie + Session 登录,第二种Token 登录,第三种SSO 单点登录,第四种OAuth 第三方登录,除了第四种的OAuth没有了解接触过,其他三种都有所了解,当前我们的项目有对登陆部分的需求,所以今天写下这个记录一下,顺便把目前项目的登陆流程熟悉熟悉。
3. 当前我们的一个后台使用的登陆方法为Session+Cookie的方式进行登陆,由于服务器端需要对接大量的客户端,也就需要存放大量的 SessionId,这样会导致服务器压力过大。如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。在项目初期的需求讨论中,要将这个后台合进一个大型的中台中,通过跳转的模式进入这个项目,决定不使用单独的登陆,使用SSO 单点登录,统一内部所有产品的登录方式,而进行到现在,需要将本项目的登陆对接,所以将目前的登陆总结如下
登陆总结:
一.api
1.1 统一处理请求url(url加上serverPath对接环境配置变量)
Const rq = name => appconfig.sserverPath+'/'+name
const API = {
login:rq(api.SET_LOGIN) //替换url加上环境配置变量
}
1.2 接口函数
1.2.1 获取session信息接口
const getSession = () => Axios({method:"post",url:API.login})
1.2.2 获取登陆信息接口
const getLogin = (data) => Axios({method:"post",url:API.login,,data:data})
1.2.3 获取首页信息接口
const getAuthreSource = () => Axios({method:"post",url:API. getAuthreSource})
1.2.4 获取用户菜单权限接口
const getUserMenuPowlist = () => Axios({method:"post",url:API. getUserMenuPowlist})
二.cookie
2.1 截取cookie解码信息getCookieVal
unescape(doc.cookie.substring(offset,endstr))
2.2 获取cookie(getCookie)
传入参数name获取cookie,然后调用getCookieVal()解码
2.3 存cookie (setCookie)
传入参数,name,value,delay,
new Date().setTime(new Date().getTime() + delayTime) //delayTime有默认值
doc.cookie = `${name}=${escape(value)};expires=${new Date().toGMTString()};path=/`
2.4 删除cookie (delCookie)
传入参数,name
new Date().setTime(new Date().getTime() - 100)
var cval = getCookie(name) //获取cookie
doc.cookie = `${name}=${cval};expires=${new Date().toGMTString()};path=/`
2.5 crud => Session + Local
三.vuex处理
3.1 state
从localStorage获取session,userinfo,menulist,menuitemlist
3.2 getters
从state里获取登陆态,菜单权限,用户信息,session会话信息
3.3 actions调用mutations
存储和清除sessionn信息,userinfo信息,存储菜单权限信息
四.登陆流程
4.1 进入登陆页面调用接口获取Session,存入vuex
const iCIFID。= res.headers.icifid || res.data.header.iCIFID
this.submitSessionInfo({iCIFID}) //存储Session
const checkCodeSrc = `${API.getCheckCodeUrl}?nocache=${Date.now()}&iCIFID=${iCIFID}`
This.checkCodeSrc = checkCodeSrc
4.2 加密密码and登陆校验
使用md5加密密码,校验是否输入内容(用户名,密码,验证码)
4.3 调用登陆接口
4.3.1 成功后调用菜单权限接口
4.3.1.1 将菜单数据处理为数组
4.3.1.2 将菜单分为1.2.3.4级菜单
4.3.1.3 调用2.3.4级菜单方法,将子菜单分别接收
4.3.1.4 将4级菜单和menuType为3的数组存进vuex
4.3.2 再调用存储用户信息方法,将用户信息存入vuex
4.3.3 数据统计(window.zhuge为挂载全局的方法,检测,埋点用,此处不做详细说明)
window.zhuge?.identify(res.data.body.cstNo,{name:res.data.body.cstName})
4.3.4 判断是否从别的页面跳转而来,如果是登陆后直接到该页面
const rediectUrl = this.$route.query.rediectUrl
if(rediectUrl) this.$router.push(decodeURIComponent(rediectUrl))
else this.$router.push("/about")
4.3.5 清验证码,调用清楚验证码方法
五.接口Axios处理(不同项目会有不同)
5.1 获取axios
axios = axios.create({baseUrl,timeout,responseType,withCredentials})
5.2 获取请求数据的主体(处理请求头和请求体)
判断请求头中type的类型,来选择反序列化处理body还是转换为json(具体代码不做演示)
5.3 请求拦截器
5.3.1 处理请求头
let headers = {type,token,iCIFID,eCIFID,encry,channel,“Accept”,“Content-Type”}
5.3.2 判断是否有请求体,调用5.2所说的处理函数修改data
5.3.3 处理完毕 返回config
5.3.4 配置请求错误
5.4 响应拦截器
5.4.1 判断res.data是否存在body
5.4.2 判断是否有错误码,将错误响应页面
5.4.3 判断错误status[403,404,500,502],设置不同报错信息
这是目前使用的传统session+cookie的方式登陆,后续会再记录对接单点登录的内容,这个文章仅对于本人是一个记录,所以其中的一些不清楚的地方,我做一个简单的备注,各位有疑惑的可以留言。
附言:
1.上述的doc为window.document
2.cookie的使用在上面没有体现到,因为是在登陆以后的一个vue文件做了处理,只是为了更加全面的总结,我把js方面的全部进行的大概的总结