首页 > 其他分享 >事件处理系统--token

事件处理系统--token

时间:2023-02-09 17:44:38浏览次数:52  
标签:事件处理 用户 请求 登录 -- Token next token

技术:vue2+node.js

一、token

​ Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。

​ Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

​ Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

二、token的流程

image-20230209164908836

三、vue中的配置

1.获得token并存储在本地

​ ps:我使用的vuex来进行数据管理

a.页面

<script>
  export default {
    data(){
      return{
          // 用户名
        username:'',
          // 密码
        password:''
      }
    },
    methods:{
        // 登录函数
      async login(){
        const {username,password} = this
        try {
            // 通过 store.dispatch 方法触发Action
          await this.$store.dispatch('userLogin',{username,password} )
            // this.$route.query.redirect:原本你想去的路由
          let goPath = this.$route.query.redirect||'/home';
          // 跳转到首页
          this.$router.push(goPath);
          alert("登录成功")
        } catch (err) {
          alert(err.message)
        }
      }
    }
  }
</script>

​ 在form表单中填写用户名和密码后,调用store.dispatch 方法触发Action中的userLogin

b.vuex

(1).action中

	 //用户登录
     async userLogin({commit}, data) {
          // reqUserLogin是我封装的登录请求,data包含了username和password
          let result = await reqUserLogin(data);
          //登录成功
          if (result.code == 0) {
              // 存储token
               commit('SET_TOKEN', result.data.token);
               //获取token【持久化存储】,将token存入本地缓存
               localStorage.setItem('TOKEN', result.data.token);
               return 'ok';
          } else {
               //登录失败
               return Promise.reject(new Error(result.message));
          }
      },

(2).state中

let state = {
    // 获取本地存储的token,当token不存在时,取为空
    token: localStorage.getItem("TOKEN") || '',
};

(3).mutations中

let mutations = {
    SET_TOKEN(state, token) {
          state.token = token
    }
};

c.请求

index.js

//统一管理项目全部的接口
import requests from "./requests";
import qs from 'qs';

//登录的接口:请求体携带参数 username&&password
export const reqUserLogin = (data)=>requests({url:`/api/login`,method:'post',data:qs.stringify(data)});

2.请求携带token的配置

​ ps:这里我对axios二次封装了

requests.js

//对于axios进行二次封装
import axios from "axios";
//获取仓库:存储数据
import store from "@/store";

//axios.create方法执行,其实返回一个axios和request一样的
let requests = axios.create({
    //超时的设置
    timeout: 5000
});


//请求拦截器:将来项目中【N个请求】,只要发请求,会触发请求拦截器!!!
requests.interceptors.request.use(config => {
    //请求拦截器:请求头【header】,请求头能给服务器携带参数
    //请求拦截器:给服务器携带请求们的公共的参数
    //token[公共参数]
    if(store.state.user.token){
        config.headers.Authorization  = store.state.user.token;
    }
    return config;
});


//响应拦截器:请求数据返回会执行
requests.interceptors.response.use((res) => {
    //res:实质就是项目中发请求、服务器返回的数据
    return res.data;
}, (err) => {
    //温馨提示:某一天发请求,请求失败,请求失败的信息打印出来
    alert(err.message);
    //终止Promise链
    return new Promise();
});


//最后需要暴露:暴露的是添加新的功能的axios,即为requests
export default requests;

​ 有了请求拦截器之后,后续的请求都可以自动携带state中的token了。

3.token过期的操作

​ 如果token为空或者过期,后端会发相应的错误码,让你重新登录。

​ 此时的步骤大致为:

​ 1.清除本地的token

​ 2.重新登录获取token

4.限制用户未登录时的路由跳转

​ 有时候用户并没有登录,这时候个人信息等界面都不能进行路由跳转

​ 这时候就需要路由守卫---主要用来通过跳转或取消的方式守卫导航

//全局守卫:只要项目中有任何路由变化,全局守卫都会进行拦截【符合条件走你,不符合条件不能访问】
//全局守卫:全局前置守卫【访问之前进行触发】

//全局前置守卫
router.beforeEach(async (to, from, next) => {
    //to:去的那个路由的信息
    //from:从那个路由而来的信息
    //next:放行函数!!!!!! 
    //第一种:next(),放行函数,放行到它想去的路由!!!
    //第二种:next(path),守卫指定放行到那个路由去?
    //用户是否登录:取决于仓库里面是否有token!!!
    //每一次路由跳转之前需要用有用户信息在跳转,没有发请求获取用户信息在跳转!!!!
    //token
    let hasToken = store.state.user.token;
    //用户信息
    let hasNickName = store.state.user.username;
    //用户登录
    if (hasToken) {
        //用户登录了,不能去login
        if (to.path == "/login") {
            next('/home');
        } else {
            //用户登陆了,而且还有用户信息【去的并非是login】
            if (hasNickName) {
                next();
            } else {
                //用户登陆了,但是没有用户信息 
                try {
                    //发请求获取用户信息以后在放行
                    await store.dispatch('getUserInfo');
                    next();
                } catch (error) {
                    //用户没有信息,还携带token发请求获取用户信息【失败】
                    //token【学生证失效了】
                    //token失效:本地清空数据、服务器的token通知服务器清除
                    await store.dispatch('logout');
                    //回到登录页,重新获取一个新的学生证
                    console.log("用户没有信息,token失效");
                    next('/login');
                }
            }
        }
    } else {
        //用户未登录||目前的判断都是放行.将来这里会'回手掏'增加一些判断
        //用户未登录:不能进入/trade、/pay、/paysuccess、/center、/center/myorder  /center/teamorder
        // let toPath = to.path;
        // if (toPath.indexOf('trade') != -1 || toPath.indexOf('pay') != -1 || toPath.indexOf('center') != -1) {
        //     next('/login?redirect='+toPath);
        // } else {
        //     next();
        // }
        next();
    }
});

四、node.js中的配置

1.配置跨域

​ 1.运行如下的命令,安装 cors 中间件:

npm i [email protected]

​ 2.在 app.js 中导入并配置 cors 中间件:

// 导入 cors 中间件
const cors = require('cors')
// 将 cors 注册为全局中间件
app.use(cors())

2.生成token

在生成 Token 字符串的时候,一定要剔除 密码的值!!!!!!!

​ 1.通过 ES6 的高级语法,快速剔除 密码的值:

// 剔除完毕之后,user 中只保留了用户的 id, username, nickname, email 这四个属性的值
const user = { ...results[0], password: '', user_pic: '' }

​ 2.运行如下的命令,安装生成 Token 字符串的包:

npm i [email protected]

​ 3.在 /router_handler/user.js 模块的头部区域,导入 jsonwebtoken 包:

// 用这个包来生成 Token 字符串
const jwt = require('jsonwebtoken')

​ 4.创建 config.js 文件,并向外共享 加密还原 Token 的 jwtSecretKey 字符串:

module.exports = {
  jwtSecretKey: 'itheima No1. ^_^',
}

​ 5.将用户信息对象加密成 Token 字符串:

// 导入配置文件
const config = require('../config')

// 生成 Token 字符串
const tokenStr = jwt.sign(user, config.jwtSecretKey, {
  expiresIn: '10h', // token 有效期为 10 个小时
})

​ 6.将生成的 Token 字符串响应给客户端:

res.send({
  status: 0,
  message: '登录成功!',
  // 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀
  token: 'Bearer ' + tokenStr,
})

3.解析token

​ 1.运行如下的命令,安装解析 Token 的中间件:

npm i [email protected]

​ 2.在 app.js 中注册路由之前,配置解析 Token 的中间件:

// 导入配置文件
const config = require('./config')

// 解析 token 的中间件
const expressJWT = require('express-jwt')

// 使用 .unless({ path: [/^\/api\//] }) 指定哪些接口不需要进行 Token 的身份认证
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api\//] }))

​ 3.在 app.js 中的 错误级别中间件 里面,捕获并处理 Token 认证失败后的错误:

// 错误中间件
app.use(function (err, req, res, next) {
  // 省略其它代码...

  // 捕获身份认证失败的错误
  if (err.name === 'UnauthorizedError') return res.cc('身份认证失败!')

  // 未知错误...
})

标签:事件处理,用户,请求,登录,--,Token,next,token
From: https://www.cnblogs.com/ljer/p/17106468.html

相关文章