用户进入网站首次登录,前端会携带用户信息(用户名、密码什么的)到服务端做请求
1、服务端验证用户名密码
未通过校验:响应给前端,用户名/密码错误等信息
通过校验:对该用户创建token,并将token作为响应数据返回给前端
2、前端拿到响应数据:
错误信息:页面给予提示:用户名/密码错误
正常信息:页面进行跳转进入首页,保存token (可以保存在cookie或localstorage)
3、用户点击触发请求:
【路由守卫】(全局——Vue中的 beforeEach())
判断即将进入的页面需不需要token(例如:路由配置中 meta{authRequired:true})
不需要:next()放行,展示页面
需要:从本地获取token(获取到则发起请求,没获取到则返回登录页引导登录)
- router.beforeEach((to, from, next) => {
- const token = localStorage.getItem('token')
- // 目标路由不是登录页,并且还需要token验证,还没有token,那就直接给返回到登录页
- if (to.name !== 'Login'&& to.meta.authRequired && !token){
- next({ name: 'Login' })
- }else{
- // 目标路由是登录页-自然不需要token验证
- // 或目标路由不需要身份验证
- // 又或目标路由非登录页,需要token验证,但是有token
- // next放行
- next()
- }
- })
存在token,向服务器发起请求时,需要携带token
避免代码冗余,每次请求都要配置token到请求头中,所以适用【请求拦截器】
- const request = axios.create({
- baseURL: 'http://localhost:3000',
- timeout: 5000,
- })
- // 请求拦截器存在两个函数参数,分别是允许请求发送,不允许请求发送
- request.interceptors.request.use(
- // config 就是请求对象
- (config) => {
- const token = localStorage.getItem('token')
- // 将token添加到请求对象的请求头中,跟随请求一并发送至服务器
- if (token) config.headers.Authorization = `Bearer ${token}`;
- // 请求拦截器,允许请求发送的话别忘了给请求对象返回出去,否则请求发不出去
- return config
- },
- (error) => Promise.reject(error),
- )
4、服务端校验token
token这个东西呢,是由服务端生成的,但是不由服务端保存,那咋校验?
是通过某种算法,配置密钥对用户信息进行加密
服务端拿到token后会使用密钥再对其进行解密,解密出用户信息
token校验有效:通过,根据请求信息给予响应数据
token校验无效:(比如存到了localstorage中,被懂些技术的用户修改了;或token过期了)
无论怎样都是无效,服务端解密不出来,所以给予前端响应(譬如响应状态码401)
5、前端处理服务端给予的响应
为了在服务端响应后,在页面展示前对响应做出处理,使用【响应拦截器】
当状态码时401就说明token校验失败,给予用户提示/跳转到登录页面
token通过了校验,前端根据响应数据做出展示
- // 这里我们假设通过后端响应的数据中的success值判断响应是否成功
- request.interceptors.response.use(
- (response) => {
- const { status, data,message } = response
- if(data.success){
- // 交由.then处理
- return data
- }else{
- // 假设后端返回状态码401代表token失效,切换到登录页面
- if (status === 401) {
- router.push({ name: 'Login' })
- }
- // 将错误信息通过Promise返回,
- return Promise.reject(message )
- }
- },
- error=>{
- return Promise.reject(error)
- }
- )
请求/响应拦截器干啥呢?相同的请求/响应处理放到拦截器里,避免冗余;不同的各自处理。
由于token由后端生成,所以前端只能验证有没有token,不能验证其有效性