1

前言

因为业务性质原因,之前的项目,其实没有做账号管理,默认登录。
最近要求做账号权限管理,所以需要在api请求中验证token。

前端逻辑

  • 登录的时候后端返回一个token。
  • 登陆成功,token写入sessionStorage/localStorage。
  • vuex存储token。
  • axios拦截请求,请求头判断token是否存在,如果存在,设置自定义字段config.headers.Token = token
  • axios拦截响应,获取HTTP状态,如果状态为401,即未登录/登陆过期,情况本地相关token信息,跳转到登录页。
  • 其他设置Content-Type、数据格式化
  • 跨域相关设置withCredentialscrossDomain

后端逻辑

  • 设置支持自定义字段token。
  • Access-Control-Allow-Headers:x-requested-with,content-type,token
  • 拦截OPTIONS请求,返回200。如果跨域,需要设置跨域允许,否则前端不能正确得到OPTIONS结果。
  • 对于GET/POST请求,检测请求头中的token字段,校验结果决定是否走下一步流程。
  • 如果校验通过,走正常的业务逻辑。否则,设置HTTP状态为401,中断业务流程,返回校验结果。

问题

解决过程中,容易出现以下问题:

  • 前端拦截请求的时候,设置自定义字段,首字母大小写。必须大写
  • 后端处理OPTIONS请求的时候,不能正确设置允许跨域,导致前端不能正确得到OPTIONS请求结果,GET/POST请求没有发出。

结语

问题总是解决不完的,每解决完一个问题,都是一次收获!
附上前端js代码:

//设置post的默认格式为form-data
//请求拦截:如果存在token,则把token带在请求头上发送出去
axios.defaults.withCredentials = true;
axios.defaults.crossDomain = true;
axios.interceptors.request.use((config) => {
    config.headers = {'Content-Type':'application/x-www-form-urlencoded'}
    let token = store.state.token;
    if (token) {
        config.headers.Token = token;
    }
    config.data = qs.stringify(config.data, {arrayFormat: 'brackets'});
    return config;
});
//响应拦截:如果htpp状态401,则是需要登录,清除token,跳转到登录页
axios.interceptors.response.use(res =>{
    return res
}, error => {
    if(error.response && error.response.status === 401){
        store.commit('clearToken')
        router.replace({
            path: '/login',
        })
    }
    return Promise.reject(error.response ? error.response.data : error)
})

陈其文
430 声望19 粉丝

前端