vue beforeEach 路由拦截 cookie 登录管理 jsonwebtoken 表单提交校验 sessionStorage localStorage

9 篇文章 0 订阅

server\security\token.ts
使用jsonwebtoken生成token,本demo没有使用token的过期时间属性

server\index.ts
其他express服务器提供的api,验证用户登录信息。
如果用户登录成功,往用户cookie里有token信息(包含user信息)。cookie有效期10秒

src\router\index.ts
用router.beforeEach对所有url进行拦截,如果to.matched数组里有meta.needlogin:true属性的对象,说明需要登录后才能访问。对于此类路径,如果cookie的token里没有user信息(说明用户没有登录),则通过next(‘/login’)跳转登录页面。其他情况下next()直接放行。
localStorage:浏览器多个页面共享数据
sessionStorage :单个页面的数据
localStorage和sessionStorage 在vue文件可以直接使用,在ts文件不能直接使用

meta.needlogin:true属性在routes的对应url下用
meta: {
  needlogin: true,
}设置

src\utils\cookie.ts
网上随便找的cookie的工具类,包含cookie的添加,清楚,查询方法。
不知道什么原因,vue-cookie和js-cookie在非服务器的ts文件里都用不了。

src\views\login\login.vue
登录页面。
rules里 { required: true, message: “请输入”, trigger: “blur” }设置了blur时进行校验(提交时不校验),按下按钮提交时this.$refs.loginFormC.validate(valid) 再次对表单进行校验。

src\components\content.vue
提供logout功能,清除cookie里的token,并跳转’/’

//server\security\token.ts
import jwt from 'jsonwebtoken';
import { sign,  verify } from 'jsonwebtoken';
const secretKey = 'secretkey'   //secret
const expiresIn = 60;    //时效 (秒)

//生成jwt
export const generateToken=(user:string) =>{ 
    const token = jwt.sign({user}, secretKey, {
        expiresIn: expiresIn,
       });
    return token
}
 
//解析jwt
export const verifyToken=(token:any)=> {
    return jwt.verify(token, secretKey)
}
//server\index.ts 
const express = require('express'); 
const bodyParser=require('body-parser')
const app=express();
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
import sqlfun from './pgsql'; 
import {generateToken,verifyToken} from './security/token';

const cookieParser = require('cookie-parser');
app.use(cookieParser());

const port = 8081;
app.listen(port, () => console.log(`API服务器监听${port}端口!`));

app.post('/api/login', (req: any, res: any) => {
    if(req.body.user=='aa'&&req.body.pass=='aa'){
        const token=generateToken(req.body.user)
        res.cookie("token", token, { maxAge: 1000*10});
        res.send({status: 200,token:token})
    }else{
        res.send({status: 500})
    }

})
//src\router\index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

//verifyToken(token)在这用不了,在express服务器里可以使用
import { verifyToken } from "../../server/security/token";
import jwt_decode from "jwt-decode";
import cookie from '../utils/cookie'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/demo',
    meta: {
      needlogin: true,
    },
    component: layoutC,
    children: [
      {
        path: '',
        name: 'home',
        component: homeC,
      },
    ]
  },
  {
    path: '/login',
    name: 'login',
    component: loginC,
    meta: {
      needlogin: false,
    },
  },
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
router.beforeEach((to, from, next) => {
  const count=sessionStorage.getItem('count')||'0'
  sessionStorage.setItem('count',1+parseInt(count)+'')
  const count2=localStorage.getItem('count')||'0'
  localStorage.setItem('count',2+parseInt(count2)+'')

  console.log('to', to.matched)
  console.log('sessionStorage',sessionStorage.getItem('count'))
  console.log('localStorage',localStorage.getItem('count'))
  if (to.matched.length == 0) {
    console.log(1)
    next()
    return
  }
  if (to.matched.some(ele => ele.meta.needlogin)) {
    const token: string = cookie.get("token") || '';
    const tokenobj: any =token?jwt_decode(token): {}
    console.log('>>',token, tokenobj)
    if (tokenobj['user']) {
      console.log(2)
      next()
    } else {
      console.log(3)
      next('/login')
    }
  } else {
    console.log(4)
    cookie.set({'a':'1','b':'3'},1)
    cookie.clear('aaa')
    next()
  }

})
export default router
//src\utils\cookie.ts
/**
 * @description 保存cookie
 * @param {Object} json 需要存储cookie的对象
 * @param {Number} days 默认存储多少天
 */
function set(json: { [x: string]: string; }, days: number) {
    // 设置过期时间
    const date = new Date(
        new Date().getTime() + days * 24 * 60 * 60 * 1000
    ).toUTCString();

    for (const key in json) {
        document.cookie = key + "=" + json[key] + "; expires=" + date;
    }
}

/** 
 * @description 获取cookie
 * @param {String} name 需要获取cookie的key
 */
function get(name: string) {
    // console.log(document.cookie, '------')
    const arr = document.cookie.split(';')
    for (const s in arr) {
        if (arr[s].split('=')[0].trim() == name)
            return arr[s].split('=')[1].trim()
    }
    return null
}

/** 
 * @description 删除cookie
 * @param {String} name 需要删除cookie的key
 */
function clear(name: string) {
    console.log('clear cookie ',name)
    const json:any = {};
    json[name]=''
    set(json, 0)
}

export default {
    set,
    get,
    clear
}
//src\views\login\login.vue
<template style="text-align: center;">
  <div>
    <h1>login</h1>
    <el-form
      ref="loginFormC"
      :model="loginForm"
      :rules="rules"
      label-width="100px"
    >
      <el-form-item label="用户名" prop="user">
        <el-input v-model="loginForm.user"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="pass">
        <el-input v-model="loginForm.pass"></el-input>
      </el-form-item>
    </el-form>
    <el-button type="success" @click="login">登 录 </el-button>
  </div>
</template>

<script>
import api from "../../api/index";
export default {
  data() {
    return {
      loginForm: {
        user: "",
        pass: "",
      },
      rules: {
        user: [
          { required: true, message: "请输入", trigger: "blur" },
          { min: 2, max: 9, message: "长度2到9", trigger: "blur" },
        ],
        pass: [{ required: true, message: "请输入", trigger: "blur" }],
      },
    };
  },
  methods: {
    login() {
      this.$refs.loginFormC.validate((valid) => {
        if (valid) {
            api.login({ user: this.loginForm.user, pass: this.loginForm.pass })
              .then((res) => {
                if (res.data.status == 200) {
                  this.$message({ message: "登录成功" });
                  this.$router.push("/demo");
                } else {
                  this.$message({ message: "登录失败", type: "error" });
                }
              });
          }
        })
    },
  },
};
</script>

<style>
</style>
//src\components\content.vue
<template>
  <div>
      <i class="el-icon-setting" @click="logout()"></i>
    </div>
  </div>
</template>

<script>
import cookie from "../utils/cookie";
export default {
  methods: {
    logout() {
      cookie.clear('token');
      this.$router.push('/');
    },
  },
};
</script>

<style lang="less" scoped>
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值