最近一直在使用 jwt(JSON Web Token),前端经过用户名、密码登录成功后,接口返回一个 jwt前端
// login exports.user_login = async function (req, res, next) { const { username, password } = req.body let ret = await userModel.userLogin(username, password) if (!ret) return next(createError(500)) // sql 执行失败,直接给 500 if (ret.length !== 1) { // 用户名或密码错误 res.json({ code: 100, message: '用户名或密码错误', data: null }) } else { const user = ret[0] const token = generateJWT(user) res.json({ code: 100, message: '返回成功', data: { token } }) } } // 生成 jwt function generateJWT(user) { let now = new Date() let expire = new Date(now).getTime() + 30 * 60 * 1000 // 30 min 后过时 return jwt.sign({ id: user.id, username: user.username, password: user.password, role: user.role, exp: expire / 1000 }, SECRET) }
前端请求成功后,收到 token,存储在本地vue
// vuex store 中 login({ commit }, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username: username.trim(), password }).then(res => { if (res) { commit('SET_TOKEN', res.token) setSessionItem('token', res.token) // 存到 sessionStorage 中 resolve(true) } else { resolve(false) } }).catch(error => { console.log('error: ', error) // for debug reject(error) }) }) }
而后之后每次请求接口都带上这个 jwtios
// 请求拦截器 axios.interceptors.request.use( config => { const token = getSessionItem('token') || '' if (token) config.headers['token'] = token return config }, error => { // 对请求错误作些什么 console.log(error) // for debug return Promise.reject(error) } )
以前作移动端是这么搞的,但今天在作 PC 端一个管理后台时,发现 jwt 存到 sessionStorage 中有个问题,同源下,不一样的窗口 sessionStorage 中的数据不能共享,就是说打开一个窗口已经登陆了,在浏览器中在开一个窗口还得从新登陆,这就不能忍了sql
因而,就想成功后,将 jwt 存到 cookie 中,这样不一样的窗口就能够共享了,这个存储后端和前端均可以作,后端存储:vuex
// login exports.user_login = async function (req, res, next) { ... const user = ret[0] const token = generateJWT(user) // express 要引入 cookie-parse res.cookie("token", token, { maxAge: 30 * 60 * 1000, httpOnly: true }) // httpOnly 为 true,js 脚本就不能访问了 res.json({ code: 100, message: '登陆成功' }) }
返回头就会有 set-cookie 这个字段了express
之后每一个请求头里面都会自带 cookie 了json
express 接收:req.cookies.tokenaxios
本着先后端彻底分离的原则,我采用前端来存 cookie,后端将生成的 token 仍是给到前端,前端引 js-cookie 这个库来操做后端
// vuex store 中 login({ commit }, userInfo) { ... if (res) { commit('SET_TOKEN', res.token) setToken(res.token) resolve(true) } else { resolve(false) } ... }
用 js-cookie 这个库设置 cookie,没有找到怎么设置 HttpOnly。浏览器