Springboot和vue前后端交互实现验证码登录

Springboot和vue前后端交互实现验证码登录

大致的思路就是:

  1. 前端发送请求到后端生成验证码图片返回给前端token,后端把验证码存在缓存中(key,value),key是token,value是验证码的值
  2. 前端拿到验证码图片渲染,并把token存在localstorage中,在发送请求前到达携带这个token
  3. 验证时,请求头中拿到token,再根据token从缓存中拿到验证码,跟前端传来的表单验证码对比

一.验证码实现流程图

二、后端具体实现步骤

2.1添加依赖

复制代码
<!-- hutool工具包 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.12</version>
</dependency>

<!-- Caffeine缓存 -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

2.2配置缓存

复制代码
@Configuration
public class CacheConfig {
    @Bean
    public Cache<String, String> captchaCache() {
        return Caffeine.newBuilder()
                .expireAfterWrite(2, TimeUnit.MINUTES)  // 2分钟过期
                .maximumSize(10000)
                .build();
    }
}

2.3验证码控制器

复制代码
@RestController
@RequestMapping("/api")
public class CaptchaController {
    
    private static final String SESSION_KEY = "X-Captcha-Token";
    
    @Autowired
    private Cache<String, String> captchaCache;
    
    // 生成验证码
    @GetMapping("/captcha")
    public void generateCaptcha(HttpServletResponse response) {
        // 生成验证码
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100, 40);
        String code = lineCaptcha.getCode();
        
        // 生成token并存入缓存
        String token = UUID.randomUUID().toString();
        captchaCache.put(token, code);
        
        // 设置响应
        response.setHeader(SESSION_KEY, token);
        response.setContentType("image/png");
        response.setHeader("Cache-Control", "no-store, no-cache");
        
        // 输出图片
        try {
            lineCaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 登录验证
    @PostMapping("/login")
    public Result login(@RequestBody LoginDTO loginDTO, 
                       @RequestHeader(SESSION_KEY) String token) {
        // 验证码校验
        String cacheCode = captchaCache.getIfPresent(token);
        if (StrUtil.isEmpty(cacheCode)) {
            return Result.error("验证码已过期");
        }
        
        if (!cacheCode.equalsIgnoreCase(loginDTO.getCaptcha())) {
            return Result.error("验证码错误");
        }
        
        // 清除验证码
        captchaCache.invalidate(token);
        
        // 继续登录流程...
    }
}

2.4跨域

复制代码
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOriginPattern("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

三.前端实现步骤

3.1验证码组件

复制代码
<template>
  <div class="captcha-wrapper">
    <input
      v-model="form.captcha"
      type="text"
      placeholder="请输入验证码"
    />
    <img 
      :src="captchaUrl" 
      @click="refreshCaptcha"
      class="captcha-img"
      alt="验证码"
    />
  </div>
</template>

<script setup>
const SESSION_KEY = 'X-Captcha-Token'

// 刷新验证码
const refreshCaptcha = async () => {
  const response = await fetch('/api/captcha')
  const token = response.headers.get(SESSION_KEY)
  localStorage.setItem(SESSION_KEY, token)
  
  const blob = await response.blob()
  captchaUrl.value = URL.createObjectURL(blob)
}
</script>

3.2axios请求配置

复制代码
// request.js
import axios from 'axios'

const SESSION_KEY = 'X-Captcha-Token'

const request = axios.create({
  baseURL: '/api',
  timeout: 5000
})

// 请求拦截器:添加token
request.interceptors.request.use(config => {
  const token = localStorage.getItem(SESSION_KEY)
  if (token) {
    config.headers[SESSION_KEY] = token
  }
  return config
})

// 响应拦截器:清理token
request.interceptors.response.use(response => {
  if (response.config.url === '/api/login' && response.data.code === 200) {
    localStorage.removeItem(SESSION_KEY)
  }
  return response.data
})
相关推荐
翱翔-蓝天25 分钟前
为什么“看起来很规范”的后端项目反而臃肿且性能下降
spring boot
LYFlied1 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
80530单词突击赢1 小时前
JavaWeb进阶:SpringBoot核心与Bean管理
java·spring boot·后端
B站_计算机毕业设计之家1 小时前
豆瓣电影数据采集分析推荐系统 | Python Vue Flask框架 LSTM Echarts多技术融合开发 毕业设计源码 计算机
vue.js·python·机器学习·flask·echarts·lstm·推荐算法
long3162 小时前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
独断万古他化2 小时前
【SSM开发实战:博客系统】(三)核心业务功能开发与安全加密实现
spring boot·spring·mybatis·博客系统·加密
xjt_09013 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
rannn_1113 小时前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
qq_12498707533 小时前
基于JavaWeb的大学生房屋租赁系统(源码+论文+部署+安装)
java·数据库·人工智能·spring boot·计算机视觉·毕业设计·计算机毕业设计
我是伪码农3 小时前
Vue 2.3
前端·javascript·vue.js