VUE+SPRINGBOOT从0-1打造前后端-前后台系统-登录实现

在现代Web应用开发中,前后端分离架构已成为主流模式。本文将详细介绍一个基于Vue.js和SpringBoot的前后端分离登录系统的设计与实现,涵盖了前端表单验证、验证码组件、后端权限处理等关键技术点。

一、前端登录页面实现

1.1 页面结构与样式

复制代码
<template>
  <div class="Login-container">
    <div class="allClass">
      <div class="titleClass"><b>欢迎登录人工智能系统</b></div>
      <!-- 表单部分省略 -->
    </div>
  </div>
</template>

<style scoped>
.Login-container {
  height: 100vh;
  background-image: linear-gradient(to bottom right, deepskyblue, darkcyan);
  overflow: hidden;
}
/* 其他样式省略 */
</style>

前端页面采用了Element UI组件库,整体布局简洁美观:

  • 使用全屏渐变背景增强视觉效果

  • 登录框居中显示,采用圆角设计

  • 响应式布局适应不同屏幕尺寸

1.2 表单验证实现

复制代码
data() {
  return {
    ruleList: {
      name: [
        {required: true, message: '请输入用户名即您的邮箱', trigger: 'blur'},
        {min: 3, max: 60, message: '长度在3-60个字符', trigger: 'blur'}
      ],
      password: [
        {required: true, message: '请输入密码', trigger: 'blur'},
        {min: 3, max: 60, message: '长度在3-60个字符', trigger: 'blur'}
      ],
      validCode: [
        {required: true, message: '请输入验证码', trigger: 'blur'},
        {min: 3, max: 4, message: '长度在3-4个字符', trigger: 'blur'}
      ]
    }
  }
}

表单验证特点:

  1. 采用Element UI的表单验证机制

  2. 对用户名、密码、验证码都设置了必填和长度验证

  3. 触发方式为blur(失去焦点时验证)

1.3 验证码组件

系统集成了一个独立的验证码组件ValidCode

复制代码
<ValidCode @input="createValidCode" style="margin-left: 15px;margin-top: 5px;"/>
复制代码
methods: {
  createValidCode(data) {
    this.validCode = data
  }
}

验证码功能特点:

  • 点击可刷新验证码

  • 不区分大小写验证

  • 通过自定义事件传递验证码值

1.4 登录逻辑处理

复制代码
loginClick() {
  this.$refs["userForm"].validate(valid => {
    if (valid) { // 表单校验合法
      // 验证码校验
      if (this.user.validCode.toLowerCase() !== this.validCode.toLowerCase()) {
        this.$message.error("验证码错误")
        return false
      }
      // 发送登录请求
      this.$http.post("/big/login", this.user).then(res => {
        if (res.data.code === "200") {
          // 存储用户信息和菜单
          localStorage.setItem("user", JSON.stringify(res.data.object))
          localStorage.setItem("menuList", JSON.stringify(res.data.object.menuList))
          setRoutes() // 动态设置路由
          // 根据角色跳转不同页面
          if (res.data.object.role === "white") {
            this.$router.push("/main") // 前台首页
          } else {
            this.$router.push("/index_home") // 后台首页
          }
        } else {
          this.$message.error(res.data.message)
        }
      })
    }
  })
}

登录流程:

  1. 表单验证通过后检查验证码

  2. 发送登录请求到后端

  3. 成功后存储用户信息和菜单权限

  4. 动态设置路由

  5. 根据用户角色跳转到不同首页

二、后端登录接口实现

2.1 登录接口核心代码

复制代码
@PostMapping("/login")
public Res login(@RequestBody User user) {
    // 密码SHA256加密
    user.setPassword(MyUtils.getSHA256StrJava(user.getPassword()));
    
    // 查询用户
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.eq("name", user.getName());
    userQueryWrapper.eq("password", user.getPassword());
    User existUser = userMapper.selectOne(userQueryWrapper);
    
    if (existUser == null) {
        return Res.error(Constants.CODE_600, "用户名或密码错误");
    }
    
    // 生成Token
    String token = Token.productToken(existUser);
    existUser.setToken(token);
    
    // 处理角色权限
    Role role = new Role();
    role.setName(existUser.getRole());
    Role existRole = roleMapper.selectOne(roleQueryWrapper);
    
    // 构建菜单权限树
    List<Integer> menuIdList = new ArrayList<>();
    if (existRole.getMenuIds() != null) {
        // 处理菜单ID字符串
        String menuIds = existRole.getMenuIds().replace("[", "").replace("]", "");
        String[] tempArray = menuIds.split(",");
        for (String temp : tempArray) {
            menuIdList.add(Integer.parseInt(temp));
        }
    }
    
    // 补充父菜单ID
    List<Integer> tempList = new ArrayList<>(menuIdList);
    for (Integer menuId : menuIdList) {
        Menu menu = menuMapper.selectById(menuId);
        if (menu != null && menu.getFather() != null && !tempList.contains(menu.getFather())) {
            tempList.add(menu.getFather());
        }
    }
    
    // 构建菜单树结构
    List<Menu> menuList = menuMapper.selectBatchIds(tempList);
    List<Menu> fatherMenuList = menuList.stream()
        .filter(temp -> temp.getFather() == null)
        .collect(Collectors.toList());
    
    for (Menu item : fatherMenuList) {
        List<Menu> childrenList = menuList.stream()
            .filter(temp -> item.getId().equals(temp.getFather()))
            .collect(Collectors.toList());
        item.setChildren(childrenList);
    }
    
    existUser.setMenuList(fatherMenuList);
    return Res.success(existUser);
}

2.2 后端登录处理流程

  1. 密码加密处理

    • 使用SHA256算法对用户密码加密

    • 加密后与数据库存储的密码比对

  2. 用户查询

    • 使用MyBatis-Plus的QueryWrapper构建查询条件

    • 同时匹配用户名和密码

  3. Token生成

    • 登录成功后生成Token

    • Token将用于后续请求的身份验证

  4. 权限处理

    • 查询用户角色对应的菜单权限

    • 处理菜单ID字符串转换为列表

    • 补充必要的父菜单ID

    • 构建树形菜单结构

  5. 返回结果

    • 返回包含Token和菜单权限的用户信息

    • 前端将使用这些信息初始化路由和界面

三、关键技术点解析

3.1 动态路由实现

前端在登录成功后调用setRoutes()方法动态设置路由:

复制代码
setRoutes() // 动态设置路由

原理是根据后端返回的菜单权限,动态添加路由配置,实现权限控制。

3.2 密码安全策略

  1. 前端不存储密码明文

  2. 传输过程建议使用HTTPS

  3. 后端使用SHA256加密存储

  4. 数据库不存储明文密码

3.3 菜单权限树构建

后端通过以下步骤构建菜单树:

  1. 从角色配置中获取菜单ID列表

  2. 补充必要的父菜单ID

  3. 查询完整的菜单信息

  4. 构建父子关系的树形结构

复制代码
List<Menu> fatherMenuList = menuList.stream()
    .filter(temp -> temp.getFather() == null)
    .collect(Collectors.toList());

for (Menu item : fatherMenuList) {
    List<Menu> childrenList = menuList.stream()
        .filter(temp -> item.getId().equals(temp.getFather()))
        .collect(Collectors.toList());
    item.setChildren(childrenList);
}

四、系统扩展与优化建议

  1. 登录安全增强

    • 添加登录失败次数限制

    • 实现IP异常检测

    • 考虑添加二次验证

  2. 性能优化

    • 菜单权限缓存

    • Token刷新机制

    • 接口响应优化

  3. 功能扩展

    • 第三方登录集成

    • 多因素认证

    • 登录日志记录

五、总结

本文详细介绍了基于Vue和SpringBoot的前后端分离登录系统的设计与实现,涵盖了从前端表单验证到后端权限处理的完整流程。该系统具有以下特点:

  1. 前后端完全分离,通过API交互

  2. 完善的表单验证机制

  3. 动态路由和权限控制

  4. 安全的密码处理策略

  5. 灵活的菜单权限配置

通过这种架构,系统具有良好的扩展性和维护性,可以方便地适应各种业务需求的变化。

相关推荐
weixin_382395232 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__2 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.3 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~4 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华4 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
立心者06 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
做前端的娜娜子7 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅7 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni7 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法