跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

Vue2+SpringBoot 在线商城 02-前后端登录功能对接

综述由AI生成基于 Vue2 和 SpringBoot 的在线商城项目中登录功能的实现过程。后端通过添加 jjwt 和 hutool 依赖,编写了日期工具类和 JWT 工具类用于 Token 生成与验证。完善了用户实体类并实现了登录控制器,采用 MD5 加盐方式处理密码,暂时使用硬编码账号进行测试。前端调用登录接口,接收返回的 JWT Token 并进行解析展示。测试环节验证了正确与错误账号下的接口响应情况,完成了前后端登录流程的初步打通。

菩提发布于 2026/4/6更新于 2026/5/2223 浏览
Vue2+SpringBoot 在线商城 02-前后端登录功能对接

本项目是基于 Vue2+SpringBoot+Mysql 制作的在线商城项目。

之前已经实现了后端 Result,也实现了前后端的连通测试。接下来先逐步实现登录功能。不过目前先不连接数据库,先把登录的相关接口和 MD5 加密以及其他必备的功能先写好,然后后续再对接数据库。

一、后端实现

1.1 添加必要依赖

在 pom.xml 中,添加这两个依赖。

jjwt 这个依赖用于生成/校验 Token。后续在 JwtUtil 会用到。hutool-all 是用于做 md5 加密

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.24</version>
</dependency>
1.2 实现 DateTool

用于返回当前时间。

package com.xmut.backend.utils;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class DateTool {
    /**
     * 返回当前时间
     *
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String getCurrTime() {
        SimpleDateFormat longFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        return longFormat.format(calendar.getTime());
    }
}
1.3 实现 JwtUtil 工具类
1.3.1 定义相关常量

将过期时间设置为 24 小时

private static long EXPIRATION_TIME = 3600000 * 24; // 过期时间:24 小时(3600000 毫秒=1 小时)

暂时先将密钥写死

private static String SECRET = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjY34DFDSSSd";

定义两个常量

private static final String USER_ID = "id"; // 用户 ID 在 JWT 中的 key
private static final String TIME = "currentTime"; // 时间戳在 JWT 中的 key
1.3.2 实现 token 生成方法
public static String generateToken(String id) {
    HashMap<String, Object> map = new HashMap<String, Object>(); // 创建一个 hashmap 存储信息
    map.put(USER_ID, id); // 将用户 ID 放入
    String jwt = Jwts.builder()
            .setClaims(map) // 把用户信息放入 JWT
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 设置过期时间
            .signWith(SignatureAlgorithm.HS512, SECRET) // 使用 HS512 算法和密钥签名
            .compact(); // 生成最终的 JWT 字符串
    return jwt;
}

这个 put 动作,只在 Java 内存里操作,跟 JWT 还没关系,可以 put 很多次,放很多信息。 而后面的 setClaims 动作,则是将备好的信息交给 JWT 生成器,而且只能设置一次 claims。

1.3.3 实现带时间戳的 token 生成方法

代码逻辑和刚刚的 token 生成方法基本一致。多存储了一个当前的时间戳。

public static String generateTokenByTime(String id) {
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put(USER_ID, id);
    map.put(TIME, DateTool.getCurrTime());
    String jwt = Jwts.builder().setClaims(map)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(SignatureAlgorithm.HS512, SECRET).compact();
    return jwt;
}
1.3.4 实现 token 验证方法
public static Result validateToken(String token) {
    Result result = new Result();
    if (token == null || "".equals(token.trim())) {
        result.fail("missing token");
        return result;
    }
    try {
        Map<String, Object> body = Jwts.parser().setSigningKey(SECRET)
                .parseClaimsJws(token).getBody();
        Object idObj = body.get(USER_ID);
        String id = idObj == null ? null : String.valueOf(idObj);
        if (id == null || "".equals(id.trim())) {
            result.fail("Wrong token without id");
            return result;
        }
        result.setData(id);
        return result;
    } catch (Exception e) {
        result.fail(e.toString());
        return result;
    }
}
1.4 完善 User 实体类

刚刚为了测试前后端的连接,只设计了 name 字段,现在将其他需要的也补充上来,包括对应的 getter 和 setter 方法。

package com.xmut.backend.entity;

/**
 * 测试用实体类
 */
public class User {
    // 用于 postJson 测试
    private String name;
    // 用于 login 测试
    private String id;
    private String username;
    private String password;
    private String salt;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getSalt() { return salt; }
    public void setSalt(String salt) { this.salt = salt; }
}
1.5 实现一个简单的 UserController

@RequestBody 将请求的 JSON 体自动转换为 User 对象

package com.xmut.backend.controller;
import cn.hutool.crypto.digest.DigestUtil;
import com.xmut.backend.entity.User;
import com.xmut.backend.utils.JwtUtil;
import com.xmut.backend.utils.Result;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 登录接口
 * 说明:目前先不接数据库,先写死一个账号,跑通从登录到返回 token 的过程
 */
@RestController
@RequestMapping("/kmall/user")
public class UserController {
    // 先写死一个账号
    private static final String FIXED_ID = "1";
    private static final String FIXED_USERNAME = "admin";
    private static final String FIXED_SALT = "kmall_salt";
    private static final String FIXED_PASSWORD_MD5 = DigestUtil.md5Hex("123456" + FIXED_SALT);

    @PostMapping("/login")
    public Result login(@RequestBody User user) {
        Result result = new Result();
        // 从 User 对象中获取用户名和密码
        String username = user == null ? null : user.getUsername();
        String password = user == null ? null : user.getPassword();
        // 检查用户名是否为 null 或空字符串
        if (username == null || "".equals(username.trim())) {
            result.fail("用户不存在");
            return result;
        }
        // 验证用户名是否等于固定的"admin",也就是刚刚写死的用户名
        if (!FIXED_USERNAME.equals(username.trim())) {
            result.fail("用户不存在");
            return result;
        }
        // 计算用户输入密码的 MD5 值,同样也是要加上盐值
        String md5Password = DigestUtil.md5Hex((password == null ? "" : password) + FIXED_SALT);
        // 比较计算出的 MD5 值与预先计算的固定 MD5 值,如果不匹配,返回密码错误
        if (!FIXED_PASSWORD_MD5.equals(md5Password)) {
            result.fail("密码错误");
            return result;
        }
        // 成功处理
        String token = JwtUtil.generateTokenByTime(FIXED_ID);
        // 调用 JWT 工具类生成 token,传入刚刚写死的 FIXED_ID
        result.setMessage("登录成功");
        result.setData(token);
        // 将生成的 token 放入 result 的 data 字段
        return result;
    }
}

二、前端实现

2.1 实现用户登录的接口 /api/userApi.js
import { postJson } from './index'
// 用户相关接口(module 层)
// 后端:POST /kmall/user/login
export function loginRequest(username, password) {
    return postJson('/kmall/user/login', {
        username: (username || '').trim(),
        password: (password || '').trim()
    })
}
2.2 添加相关的测试按钮

测试按钮

2.3 添加必要的数据、函数

先填充好正确的测试账号和密码,可以方便测试。

testUsername: 'admin',
testPassword: '123456',
testLoginRequest: function () {
    var self = this // 保存 this 引用
    var u = (self.testUsername || '').trim() // 获取用户名
    var p = (self.testPassword || '').trim()
    loginRequest(u, p) // 调用登录函数,也就是刚刚在 userApi 里面定义的
        .then(function (response) {
            // 当 loginRequest 成功完成时,执行此回调函数
            var result = response.data // 提取响应数据
            self.handleApiResult(result) // 调用结果处理方法
        })
        .catch(function (error) {
            // 处理异步失败
            self.lastResultText = 'error: ' + error // 更新错误显示
            console.log('error:' + error) // 在控制台输出错误信息
        })
},

三、测试

3.1 输入正确的账号密码

此处 data 返回的是一个 JWT 的 token 字符串,由三段组成(用.分隔):

  • 第 1 段:header(说明用的算法,比如 HS512)
  • 第 2 段:payload(放进去的内容,比如 id,currentTime, exp)
  • 第 3 段:signature(用密钥做的签名,用来防篡改)

JWT 结构

可以解码看看:

JWT 解码

3.2 输入错误的账号/密码

得到对应的错误提示

错误提示

目录

  1. 一、后端实现
  2. 1.1 添加必要依赖
  3. 1.2 实现 DateTool
  4. 1.3 实现 JwtUtil 工具类
  5. 1.3.1 定义相关常量
  6. 1.3.2 实现 token 生成方法
  7. 1.3.3 实现带时间戳的 token 生成方法
  8. 1.3.4 实现 token 验证方法
  9. 1.4 完善 User 实体类
  10. 1.5 实现一个简单的 UserController
  11. 二、前端实现
  12. 2.1 实现用户登录的接口 /api/userApi.js
  13. 2.2 添加相关的测试按钮
  14. 2.3 添加必要的数据、函数
  15. 三、测试
  16. 3.1 输入正确的账号密码
  17. 3.2 输入错误的账号/密码
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • SystemVerilog 硬件验证实战:从基础语法到高级特性应用
  • XLeRobot VR 控制系统搭建与 Quest3 实操指南
  • OpenClaw 安装配置及 Minimax DeepSeek 飞书机器人接入
  • 自然语言处理在医疗领域的应用与实战
  • Neo4j 插件 APOC 安装与配置实战指南
  • FPGA 详解:什么是现场可编程门阵列
  • 使用 NCC 和 PKG 将 Node.js 项目打包为跨平台可执行文件
  • 执行式 AI 基础:API 调用与网络请求知识
  • Levenberg-Marquardt 非线性最小二乘优化算法 C++ 实战实现
  • 用 Claude Skill 提升大模型生成前端的审美质量
  • AI 小说生成器本地部署教程
  • GPT-OSS-20B 多用户并发 WEBUI 压力测试
  • Llama3.1 本地知识库应用部署指南
  • 开源知识库 RAGFlow 从部署到实战操作详解
  • Java 对象更新时避免空字段覆盖的几种拷贝方案
  • 使用文心一言为智能体设计稳定调用工作流的提示词
  • Linux 进程间通信:命名管道(FIFO)原理与实战
  • 华为 OD 机试:补种未成活胡杨
  • 低空经济新实践:无人机如何革新光伏电站巡检
  • Spring 事务核心:@Transactional 注解与传播机制解析

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online