Vueとjwtの検証

Vueとjwtの検証

はじめに: この記事では、vue を使用して jwt を検証する方法について説明します。

バックエンド部分については、この記事を参照してください: SpringBoot+JWT+Shiro が

vue プロジェクトを作成する方法:コマンド ウィンドウで Vue プロジェクトを作成する

データベース設計

フロントエンドコード

前の段落で取得したvue2+element-ui
element-ui コンポーネント

プロジェクト構造

ここに画像の説明を挿入

メイン.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>

インデックス.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

インデックス.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>

登録.閲覧

<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>

おすすめ

転載: blog.csdn.net/qq_51447496/article/details/132396388