vue与jwt验证

vue与jwt验证

简介:本文讲解,如何使用vue,对jwt进行验证。

后端部分看这篇文章:SpringBoot+JWT+Shiro

如何创建vue项目:用命令窗口的方式创建Vue项目

这篇文章的代码可以在这里下载:jwt项目演示

数据库设计

前端代码

我前段所采取vue2+element-ui
element-ui组件

项目结构

在这里插入图片描述

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<style lang="scss">

</style>

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'login',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/login/LoginView.vue')
  },
  {
    path: '/register',
    name: 'register',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/register/RegisterView.vue')
  },
  {
    path: '/index',
    name: 'index',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/index/IndexView.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

store

index.js
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './auth'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    auth: {
      namespaced: true, // 添加命名空间
      ...auth
    }
  }
})

auth.js
// auth.js
import axios from 'axios';
import router from '@/router';

const auth = {
  state: {
    token: null
  },
  mutations: {
    SET_TOKEN(state, token) {
      state.token = token;
    },
    CLEAR_TOKEN(state) {
      state.token = null;
    }
  },
  actions: {
    login({ commit }, loginForm) {
      return new Promise((resolve, reject) => {
        // 调用登录接口,传递登录表单数据
        axios.post('http://localhost:8989/user/login', loginForm)
          .then(response => {
            const token = response.data.data.token;
            // 将token保存到Vuex中
            commit('SET_TOKEN', token);
            // 将token保存到浏览器的localStorage中,以便在刷新页面后仍然可以保持登录状态
            localStorage.setItem('token', token);
            resolve();
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    logout({ commit }) {
      // 清除token并重定向到登录页面
      commit('CLEAR_TOKEN');
      localStorage.removeItem('token');
      router.push('/');
    },
    checkToken({ commit }) {
      const token = localStorage.getItem('token');
      if (token) {
        // 将token保存到Vuex中
        commit('SET_TOKEN', token);
      } else {
        // 如果没有token,则重定向到登录页面
        router.push('/');
      }
    },        
  },
  getters: {
    getToken(state){
        console.log("我被调用了")        
        return state.token;
    }
  }
};

export default auth;

LoginView.vue

<template>
  <div class="login-container" style="display: flex; justify-content: center; align-items: center;">
    <el-card class="login-card">
      <h2 class="login-title">登录</h2>
      <el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-width="80px" class="login-form">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="loginForm.username" placeholder="请输入用户名"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="loginForm.password" placeholder="请输入密码"></el-input>
        </el-form-item>
        <el-form-item>
          <div style="padding-left: 10%;">
            <el-button type="primary" @click="Login">登录</el-button>
            <span style="padding-left: 10%;">
              <el-link type="primary" @click="Register">注册</el-link>
            </span>
          </div>          
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import {mapActions } from 'vuex';

export default {
  data() {
    return {
      loginForm: {
        username: 'lihua2',
        password: '123456'
      },
      loginRules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ]
      }
    };
  },
  methods: {
    ...mapActions('auth', ['login']),
    Login() {
      // 验证表单
      this.$refs.loginForm.validate(valid => {
        console.log("表单验证成功")
        if (valid) {
          // 调用 auth 模块中的 login action
          this.login(this.loginForm)
            .then(() => {
              // 重定向到首页或其他页面
              this.$router.push('/index');
            })
            .catch(error => {
              console.log('登录失败:', error);
            });
        } else {
          console.log('表单验证失败');
        }
      });
    },
    Register() {
      this.$router.push('/register');
    }
  }
};
</script>

  
  <style scoped>
  .login-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
  }
  
  .login-card {
    width: 400px;
    padding: 20px;
  }
  
  .login-title {
    text-align: center;
    margin-bottom: 20px;
  }
  
  .login-form {
    margin-top: 20px;
  }
  </style>
  

IndexView.html

<template>
  <div>
    <el-button type="primary" @click="loginOut">退出</el-button>
    <el-table :data="users" style="width: 100%">
      <el-table-column prop="id" label="ID"></el-table-column>
      <el-table-column prop="username" label="Name"></el-table-column>
      <!-- 其他列... -->
    </el-table>
  </div>
</template>

<script>
import { mapActions, mapGetters } from 'vuex';
import axios from 'axios';

export default {
  
  data() {
    return {
      users: [],
    };
  },
  computed:{
    ...mapGetters('auth', ['getToken']),
    ...mapActions('auth', ['logout'])
  },
  mounted() {
    this.getAll();
  },
  methods: {
    getAll() {
      const token = this.getToken;
      console.log(token)
      axios.get(`http://localhost:8989/user/all/${token}`)
        .then(response => {
          this.users = response.data.data.data;
        })
        .catch(error => {
          console.error(error);
        });
    },
    loginOut(){
        this.logout()
        this.$router.push("/")
    }
  },
};
</script>

Register.vue

<template>
    <div class="register-container" style="display: flex; justify-content: center; align-items: center;">
      <el-card class="register-card">
        <h2 class="register-title">注册</h2>
        <el-form ref="registerForm" :model="registerForm" :rules="registerRules" label-width="80px" class="register-form">
          <el-form-item label="用户名" prop="username">
            <el-input v-model="registerForm.username" placeholder="请输入用户名"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input type="password" v-model="registerForm.password" placeholder="请输入密码"></el-input>
          </el-form-item>
          <el-form-item label="确认密码" prop="confirmPassword">
            <el-input type="password" v-model="registerForm.confirmPassword" placeholder="请再次输入密码"></el-input>
          </el-form-item>
          <el-form-item>
            <div style="padding-left: 10%;">
              <el-button type="primary" @click="Register">注册</el-button>
              <span style="padding-left: 10%;">
                <el-link type="primary" @click="Login">登录</el-link>
              </span>
            </div>          
          </el-form-item>
        </el-form>
      </el-card>
    </div>
  </template>
  
  <script>
  import axios from 'axios';
  export default {
    data() {
      return {
        registerForm: {
          username: '',
          password: '',
          confirmPassword: ''
        },
        registerRules: {
          username: [
            { required: true, message: '请输入用户名', trigger: 'blur' }
          ],
          password: [
            { required: true, message: '请输入密码', trigger: 'blur' }
          ],
          confirmPassword: [
            { required: true, message: '请再次输入密码', trigger: 'blur' },
            { validator: this.validateConfirmPassword, trigger: 'blur' }
          ]
        }
      };
    },
    methods: {
      Register() {
        const formData =        
        {
            username: this.registerForm.username,
            password: this.registerForm.password
        }
        this.$refs.registerForm.validate((valid) => {
          if (valid) {
            axios.post("http://localhost:8989/user/register", formData)
            .then(response => {
                if (response.data.code == 200){
                    console.log("注册成功")
                    alert("注册成功,现在返回登录页面>_<")
                    this.$router.push("/")
                } else {
                    alert(response.data.message)
                }
            })
          } else {
            console.log('Invalid registration form');
          }
        });
      },
      validateConfirmPassword(rule, value, callback) {
        if (value !== this.registerForm.password) {
          callback(new Error('两次输入的密码不一致'));
        } else {
          callback();
        }
      },
      Login() {
        this.$router.push("/")
      }
    }
  };
  </script>
  
  <style scoped>
  .register-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
  }
  
  .register-card {
    width: 400px;
    padding: 20px;
  }
  
  .register-title {
    text-align: center;
    font-size: 24px;
    margin-bottom: 20px;
  }
  
  .register-form {
    margin-top: 20px;
  }
  </style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客李华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值