欢迎来到科站长!

JavaScript

当前位置: 主页 > 网络编程 > JavaScript

vue3整合SpringSecurity加JWT实现登录认证

时间:2025-07-21 10:16:54|栏目:JavaScript|点击:

前段时间写了一篇spring security的详细入门,但是没有联系实际。

所以这次在真实的项目中来演示一下怎样使用springsecurity来实现我们最常用的登录校验。本次演示使用现在市面上最常见的开发方式,前后端分离开发。前端使用vue3进行构建,用到了element-plus组件库、axios封装、pinia状态管理、Router路由跳转等技术。后端还是spring boot整合springsecurity+JWT来实现登录校验。

本文适合有一定基础的人来看,如果你对springsecurity安全框架还不是很了解,建议你先去看一下我之前写过的spring security框架的快速入门:

springboot3整合SpringSecurity实现登录校验与权限认证(万字超详细讲解)

技术栈版本:vue3.3.11、springboot3.1.5、spring security6.x

业务流程:

可以看到整个业务的流程还是比较简单的,那么接下来就基于这个业务流程来进行我们具体代码的编写和实现;

前端:

新建一个vue项目,并引入一些具体的依赖;我们本次项目用到的有:element-plus、axios、pinia状态管理、Router路由跳转(注意我们在项目中使用到的pinia要引入持久化插件)

vue3中pinia的使用及持久化(详细解释)

在vue项目中新建两个组件:Login.vue(登录组件,负责登录页面的展示)、Layout.vue(布局页面,负责整体项目的布局,登录成功之后就是跳转到这个页面)

路由的定义:在router文件夹下新建index.ts文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'login',
      component: () => import('@/components/Login.vue')
    },
    {
      path: '/layout',
      name: 'layout',
      component: () => import('@/components/Layout.vue')
    }
  ]
})
 
export default router

定义Login登录组件为默认的组件,并定义Layout组件;

useToken的状态封装:在stoers文件夹下新建useToken.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { defineStore } from 'pinia'
import { ref } from 'vue'
const useTokenStore = defineStore('token', ()=>{
const token=ref()
  
const removeToken=()=>{
    token.value=''
}
 
return {token,removeToken}
},
{persist: true}
)
 
export default useTokenStore

axios的封装:在utils文件夹在新建request.ts文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import axios from "axios";
import  useTokenStore from '@/stores/useToken'
import { ElMessage } from 'element-plus';
// 先建一个api
const api = axios.create({
    baseURL: "http://localhost:8888",
    timeout: 5000
});
// 发送请求前拦截
api.interceptors.request.use(
    config =>{
const useToken = useTokenStore();
if(useToken.token){
    console.log("请求头toekn=====>", useToken.token);
    // 设置请求头
    // config.headers['token'] = useToken.token;
    config.headers.token = useToken.token;
}
        return config;
 
},
error =>{
 
    return Promise.reject(error);
}
)
 
// 响应前拦截
api.interceptors.response.use(
    response =>{
        console.log("响应数据", response);
if(response.data.code !=200){
    ElMessage.error(response.data.message);
}
 
        return response;
},
error =>{
    return Promise.reject(error);
}
)
 
export default api;

在请求前拦截,主要是为了在请求头中新增token。在request.ts中引入了useToken,并判断如果token不为空,那么在请求头中新增token。

在响应前也进行了一次拦截,如果后端返回的状态码不为200,那么就打印出错误信息;

接下来就可以在Login.vue中进行我们的登录逻辑的具体编写了(我直接将组件内容进行复制了,也不是什么太难的东西,主要还是element-plus的表单):

<template>
    <div style="font-family:kaiti" >

<!-- 注册表单 -->
<el-dialog v-model="isRegister" title="用户注册" width="30%">
    <el-form label-width="120px" v-model="registerForm">
        <el-form-item label="用户名">
            <el-input type="text"   v-model="registerForm.username"   >
              <template #prefix>
                <el-icon><Avatar /></el-icon>
              </template>
            </el-input>
        </el-form-item>
        <el-form-item label="密码">
            <el-input  type="password" v-model="registerForm.password" >
              <template #prefix>
        <el-icon><Lock /></el-icon>
        </template>
            </el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="registerAdd" >提交</el-button>
            <el-button @click="isRegister = false">取消</el-button>
        </el-form-item>
    </el-form>
</el-dialog>

<!-- 登陆框 -->
<div>
<el-form
    label-width="100px"
    :model="loginFrom"
    style="max-width: 460px"
    :rules="Loginrules"
    ref="ruleFormRef"
  >
    <el-form-item label="用户名"  prop="username">
      <el-input v-model="loginFrom.username"  clearable  >
        <template #prefix>
                <el-icon><Avatar /></el-icon>
              </template>
        </el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">

      <el-input v-model="loginFrom.password"   show-password   clearable  type="password" >
        <template #prefix>
        <el-icon><Lock /></el-icon>
        </template>
      </el-input>
    </el-form-item>

    <el-form-item label="验证码"  prop="codeValue">
      <el-input v-model="loginFrom.codeValue"  style="width: 100px;"  clearable  >
      </el-input>
      <img :src="codeImage" @click="getCode" style="transform: scale(0.9);"/>
    </el-form-item>

    <el-button type="success" @click="getLogin(ruleFormRef)"  style="transform: translateX(50px)" >登录</el-button>
    <el-button type="primary" @click="isRegister=true">注册</el-button>
  </el-form>

</div>

    </div>
</template>

<script setup>
import { ref,onMounted,reactive } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import useTokenStore  from '@/stores/useToken'
import  api  from '@/utils/request'
import type { FormInstance, FormRules } from 'element-plus'
const ruleFormRef =  ref<FormInstance>()

const loginFrom=ref({
username:'',
password:'',
codeKey:'',
codeValue:''
})

const Loginrules=reactive({

  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur'}
  ],
  codeValue: [
    { required: true, message: '请输入验证码', trigger: 'blur' }
  ]

})

const registerForm=ref({
  username:'',
  password:''
})

const codeImage=ref('')

const isRegister=ref(false)

const tokenStore = useTokenStore();


const router = useRouter()



const getLogin = async(formEl: FormInstance | undefined) => {

  if (!formEl)  return

  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
      
    } else {
      ElMessage('请输入完整信息')
      return;
    }
  })

  let {data}=await api.post('/user/login',loginFrom.value)

if(data.code==200){
  ElMessage('登录成功')
  console.log(data);
  tokenStore.token=data.data
  router.replace({name:'layout'})
}else{

  ElMessage('登录失败')
}


}


const getCode=async()=>{
  let {data}=await api.get('/getCaptcha')
  loginFrom.value.codeKey=data.data.codeKey
  codeImage.value=data.data.codeValue

}

const registerAdd=async()=>{
let {data}=await api.post('/user/register',registerForm.value)

if(data.code==200){
  ElMessage('注册成功')
  isRegister.value=false
}else{

  ElMessage('注册失败')
  isRegister.value=false
  }

}

// 页面加载完成获取验证码

onMounted(()=>{
getCode()

})


</script>

这个页面中,我还加入了一个图形验证码。还有一个注册的表单。其他的就和普通的登录一样了;

这个页面的最终效果如图:


上一篇:一文详解如何将Javascript打包成exe可执行文件

栏    目:JavaScript

下一篇:vue3中pinia的使用及持久化的实现

本文标题:vue3整合SpringSecurity加JWT实现登录认证

本文地址:https://www.fushidao.cc/wangluobiancheng/23723.html

广告投放 | 联系我们 | 版权申明

申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:257218569 | 邮箱:257218569@qq.com

Copyright © 2018-2025 科站长 版权所有冀ICP备14023439号