ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

数据库课程设计进阶:用户登录系统全链路解析与实现

数据库课程设计进阶:用户登录系统全链路解析与实现 简介数据库设计是后端系统开发的基石良好的表结构、约束与索引直接影响业务的安全性与性能。用户登录功能虽看似基础实则涵盖数据模型设计、完整性约束、事务处理、密码加密存储如BCrypt及会话鉴权如JWT等核心环节。理解这些原理不仅能保障数据一致性也能有效防御SQL注入等常见攻击。在课程设计或企业项目的前后端分离架构中Spring Boot、MyBatis、Vue3与MySQL是主流技术组合通过合理分层实现注册、登录、权限管理等完整链路。本文以用户登录系统为例从数据库表设计、后端接口实现到前端联调完整解析一套可运行、可答辩的课程设计方案并针对常见边界情况给出测试与优化建议帮助开发者真正掌握数据库工程化实践。 每年到了课程设计季我都会收到一批类似的私信标题写着数据库课程设计-前端后端实现用户登录等一系列操作(源码)上来第一句话往往是这个题目是不是太简单了把用户登录当成课程设计选题在很多人眼里属于偷懒。但做了这么多次指导之后我的看法完全反过来了——用户登录这套题恰恰是数据库课程设计里最值得深挖的一个。它表面上是输入用户名密码、点登录、进页面背后却牵扯出数据库表结构设计、约束完整性、索引使用、事务处理、密码安全存储、会话管理、前后端接口约定、权限控制这一整条链路。能把这条链路从头到尾讲清楚的人答辩通过率非常高。这篇文章我就是来帮你把这条链路拆明白的。我会从数据库表设计讲起逐步走到后端接口实现再到前端页面联调最后聊聊运行源码和答辩时老师最爱问的那些坑。全程基于一套实际可跑通的方案后端 Spring Boot MyBatis前端 Vue3 Element Plus数据库 MySQL这几样组合是课程设计里最稳妥也最好解释的技术栈。1. 为什么课程设计要选用户登录这套组合很多同学把登录系统理解成比对一下用户名密码如果只是这个层面那确实不值得作为一个课程设计。但实际上一个合格的登录系统需要处理注册、密码加密、登录鉴权、会话过期、用户信息维护、修改密码、权限区分、操作留痕等一系列问题。这些功能恰好对应了数据库课程设计大纲里的主要考核点概念结构设计、逻辑结构设计、完整性约束、安全性控制、以及基本的增删改查能力。1.1 课程设计评分视角下登录系统的深层价值数据库课程设计不是软件开发课程设计打分核心盯的是数据库功底。这点容易被忽略。同样是登录功能A同学建一张表加两个接口就交了B同学建了用户表、角色表、登录日志表写了约束、索引、事务甚至在用户表上加了触发器自动记录更新时间和一个存储过程支持分页查用户——你觉得老师会给谁高分答案是B。因为数据库课程设计的评分表里ER模型完整性、关系模式规范化程度、约束定义、索引使用、事务处理能力这几项分值占比很高。登录系统要展示这些东西太容易了用户表 角色表说明你理解多表关联和主外键约束登录日志表说明你理解冗余存储与分析查询的边界username 唯一索引 create_time 普通索引说明你理解索引的适用场景注册和登录接口开启事务说明你理解并发写入场景下的数据一致性密码用 BCrypt 哈希存储说明你关注数据安全。我在指导时最常说的一句话是别把课程设计当成写代码把它当成一次数据库设计的完整汇报。代码只是表达手段数据库设计才是你真正要卖给老师的东西。1.2 技术栈选型为什么是 Spring Boot Vue3 MySQL课程设计的技术栈选择核心原则不是越新越好越复杂越好而是你在答辩时能说清楚它。Spring Boot MyBatis Vue3 MySQL 是我最推荐的组合理由也很实在Spring Boot 封装性强一个注解就能启动 Web 服务不需要像 SSM 那样写一大堆 XML 配置MyBatis 的 SQL 是你自己控制的老师问你怎么查用户的你直接把 SQL 拿出来讲远比 ORM 自动生成的 SQL 更好解释MySQL 作为课程数据库普及率高老师的运行环境也基本默认有避免出现数据库迁移问题。前端选 Vue3 而不是 JSP 的原因更简单前后端分离是当前工程主流你在课程设计里体现这个趋势本身就是加分项。而且 Vue3 的组件化写法直观页面代码量比 JSP 这种模板渲染方式少很多。提示如果你所在的学校课程还没讲到 Spring Boot那可以考虑 Servlet JSP MySQL 的旧方案。但只要能选择建议还是走 Spring Boot 路线它不仅是课程作业对你后续找实习、做项目都有直接帮助。2. 数据库端设计不止建一张用户表那么简单很多同学拿到这个题目第一时间想到的就是create table user然后写 id、username、password 三个字段就结束了。这种表能跑通登录但老师在评审表结构设计时大概率会打一个中低分。原因不难理解真实业务系统里的用户表字段设计远比这复杂约束也远比这严格。2.1 用户表字段设计的十个细节我在实际项目中整理了一套用户表的设计范式拿来做课程设计刚好合适。下面是核心字段及设计意图字段名类型约束设计说明idBIGINTPRIMARY KEY AUTO_INCREMENT自增主键课程设计场景足够usernameVARCHAR(50)NOT NULL, UNIQUE登录名唯一性靠唯一索引保证passwordVARCHAR(60)NOT NULL存 BCrypt 哈希值不能存明文nicknameVARCHAR(50)DEFAULT 显示昵称登录后展示emailVARCHAR(100)DEFAULT NULL拓展字段可做找回密码phoneVARCHAR(20)DEFAULT NULL拓展字段可做手机号登录avatarVARCHAR(255)DEFAULT NULL头像路径statusTINYINTDEFAULT 11正常 0禁用禁用用户不允许登录roleVARCHAR(20)DEFAULT user区分普通用户和管理员create_timeDATETIMEDEFAULT CURRENT_TIMESTAMP注册时间不需要手动写入update_timeDATETIMEDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP更新时间每次更新自动刷新这里有几个关键点我单独拿出来说密码字段长度设为 60不是拍脑袋定的。BCrypt 算法生成的哈希值是固定 60 个字符所以 VARCHAR(60) 刚好如果你用 MD532位或者 SHA-25664位字段长度要跟着变。关于为什么不用 MD5后面我会专门讲。status 字段是很多初学者漏掉的设计。一个真实的登录系统一定需要考虑用户被封禁了怎么办查询时带上status 1条件就能实现禁用逻辑。这个字段虽然小但答辩时能体现你对业务边界的思考。role 字段先不要做成单独的角色表课程设计保持简单。有些同学急于展示多表关联能力一上来就搞 user_role、role_permission 三张表结果把自己绕晕了。先用一个role字段解决问题如果老师追问权限扩展你再提一句生产环境会拆成角色表就足够了。2.2 日志表与扩展表让答辩时有话可说用户表之外我强烈建议你加两张表。第一张是登录日志表login_log第二张是操作日志表operation_log。这两张表的存在有双重意义第一它们让登录系统闭环——用户登录后这条行为被记录下来了能查谁在什么时间登录过第二它们天然适合展示数据库里的写多读少场景你可以在课程设计报告里写登录日志表采用追加写入模式定期按时间归档。登录日志表的设计也比较直接CREATE TABLE login_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, login_time DATETIME DEFAULT CURRENT_TIMESTAMP, login_ip VARCHAR(50), status TINYINT DEFAULT 1 COMMENT 1成功 0失败, message VARCHAR(255) COMMENT 失败原因, CONSTRAINT fk_user_login FOREIGN KEY (user_id) REFERENCES user(id) );操作日志表类似就是把用户执行的关键操作记录下来。课程设计里不需要做得太重登录日志表已经足够支撑你讲出多表关联查询的案例了。2.3 用视图和存储过程在答辩时加分如果还想在数据库设计上拉开差距可以考虑在脚本里加一个视图和一个存储过程。视图可以这样做CREATE VIEW v_user_login_info AS SELECT u.id, u.username, u.nickname, u.role, l.login_time, l.login_ip FROM user u LEFT JOIN login_log l ON u.id l.user_id;这样在查询用户最近登录信息时直接SELECT * FROM v_user_login_info WHERE username xxx就行。老师在答辩时看到视图大概率会问为什么用视图你就可以回答把用户基础信息和登录日志关联查询固化下来避免业务层每次都写复杂的 JOIN同时视图也起到隐藏敏感字段比如 password的作用。存储过程可以做一个分页查询用户列表的经典例子输入页码和每页条数返回用户列表和总记录数。这种存储过程在课程设计中非常讨巧它同时体现了流程控制、动态 SQL、参数传递三个知识点。注意存储过程和视图虽然加分但如果你自己都讲不清楚原理建议不要硬加。答辩时最怕的是我抄了一段代码但不知道它为什么生效。你对每一段 SQL 的解释能力决定了这个加分项最终是加分还是减分。3. 后端搭建从 MyBatis 映射到 Token 鉴权的完整链路数据库设计完成之后就进入后端开发。后端部分的重点不是把接口写出来而是理解请求从浏览器进来之后经过哪些环节最终如何跟数据库交互。这条链路理清了老师怎么问都不怕。3.1 项目分层与依赖说明一个经典的 Spring Boot 后端项目按包名可以分成四层controller接收 HTTP 请求参数校验返回结果service业务逻辑处理事务控制mapperMyBatis 的数据访问接口entity数据库表对应的实体类common统一返回结果类、异常处理类等我见过不少课程设计代码把所有逻辑全塞在 controller 里一个方法五六百行。这样功能能跑但答辩时很难自圆其说。分层不是形式主义而是让每一层职责单一出了问题能快速定位。项目依赖方面最核心的就是这几个dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version3.0.3/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId /dependency dependency groupIdorg.mindrot/groupId artifactIdjbcrypt/artifactId version0.4/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency对课程设计来说连接池不需要自己写Spring Boot 默认集成了 HikariCP性能足够。application.yml里配置好数据源和 MyBatis 映射路径即可。3.2 登录接口BCrypt 校验与 JWT 签发登录接口是整个项目的核心我会拆成三个环节来讲参数接收、密码校验、令牌签发。参数接收直接用一个 LoginDTO 类接收前端传过来的 JSON里面包含 username 和 password。这里有一个细节password 字段在 JSON 传递过程中是明文所以生产环境必须走 HTTPS。课程设计在本地跑这个安全风险可以口头跟老师说明体现你知道这个知识点。密码校验的逻辑是我要重点强调的User user userMapper.findByUsername(loginDTO.getUsername()); if (user null) { throw new ServiceException(用户名或密码错误); } if (!BCrypt.checkpw(loginDTO.getPassword(), user.getPassword())) { throw new ServiceException(用户名或密码错误); } if (user.getStatus() 0) { throw new ServiceException(该账号已被禁用); }这里有个容易犯迷糊的点为什么查询时要把用户记录查出来再调 BCrypt.checkpw 比对因为 BCrypt 哈希值即使对同一个明文密码也不同它内含随机盐所以不能WHERE username ? AND password ?这样直接在 SQL 里比对——SQL 里没法做 BCrypt 校验。这算是 MyBatis 实践里一个很重要的认知。登录成功后后端需要生成一个令牌返回给前端。这里我选择 JWTJSON Web Token。JWT 本质上是一段包含用户信息、过期时间的签名文本后端签发后交给前端保存前端后续请求时带上它后端验证签名通过即可信任该用户身份。String token Jwts.builder() .setSubject(user.getUsername()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 2 * 60 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();为什么用 JWT 而不用传统的 Session这个问题答辩命中率极高。我的建议是这样回答Session 是保存在服务器内存里的对单体应用来说简单但服务器重启 Session 就丢了如果以后做前后端分离、多服务器部署Session 同步就变得很麻烦。JWT 是无状态的服务器不保存会话信息每次请求由前端在 Header 里携带 token后端验签即可天然适合前后端分离架构。3.3 认证拦截器哪些接口需要 token登录接口不需要 token但获取用户信息、修改资料、查询日志这些接口必须要求登录。这个必须如何实现我选择写一个拦截器。Spring Boot 的拦截器就是实现HandlerInterceptor然后在preHandle方法里校验请求头里的 token。校验通过就把用户信息放入 request 上下文校验失败则直接返回 401 和统一格式的错误信息。public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { throw new ServiceException(401, 未登录或token已过期); } Claims claims Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token.replace(Bearer , )) .getBody(); request.setAttribute(username, claims.getSubject()); return true; } }然后在 WebMvcConfigurer 里注册拦截器并配置排除路径registry.addInterceptor(jwtInterceptor) .addPathPatterns(/api/**) .excludePathPatterns(/api/auth/login, /api/auth/register);3.4 用户管理接口的 CRUD 实现除了登录和注册课程设计里一般还需要用户信息管理模块。这里我提供一套完整的接口设计和数据库表一一对应POST /api/user/update修改昵称、邮箱、手机号POST /api/user/password修改密码需要校验旧密码GET /api/user/list管理员查看用户列表支持分页和关键字搜索DELETE /api/user/{id}管理员删除用户或禁用用户GET /api/login/log查询登录日志以修改密码为例这里还必须注意一个事务问题修改密码前先校验旧密码校验通过后更新 password 字段。这两步如果分开执行中间出现异常会导致数据库处于一个不一致状态。正确的做法是在 Service 方法上标注Transactional让两步操作处于同一个事务里任何一步失败就整体回滚。Transactional(rollbackFor Exception.class) public void updatePassword(String username, String oldPwd, String newPwd) { User user userMapper.findByUsername(username); if (user null || !BCrypt.checkpw(oldPwd, user.getPassword())) { throw new ServiceException(原密码错误); } user.setPassword(BCrypt.hashpw(newPwd, BCrypt.gensalt())); userMapper.updatePassword(user); }Transactional这个注解也是答辩时的经典考点你要能说出它底层用的是 Spring AOP默认遇到运行时异常回滚rollbackFor Exception.class是为了让检查型异常也触发回滚。讲到这个层面老师基本就满意了。4. 前端实现Vue 页面如何跟后端对上话后端接口完成之后前端才能开始联调。很多同学先写前端再后端我建议反过来先用 Postman 把后端接口全部测通再动前端。这样可以极大减少调试时不知道是接口问题还是页面问题的焦虑。4.1 Vue3 Element Plus 项目的快速搭建前端工程搭建我推荐直接用 Vite 模板命令速度很快npm create vitelatest frontend -- --template vue cd frontend npm install npm install element-plus axios vue-router4Element Plus 是 Vue3 下的组件库组件风格统一表单校验做得也好特别适合课程设计的界面。安装完成后在main.js里全局注册即可。组件库的引入方式有两种全量引入和按需引入。按需引入更专业但要额外配置插件课程设计我一般建议全量引入简化配置毕竟你交的是数据库课程设计不是前端工程化课程设计。4.2 登录页表单校验与回车提交细节登录页用 Element Plus 的el-form组件绑定好校验规则注意用户名不能为空、密码不能少于6位。在这里我分享一个容易被忽略的小细节el-input 上要加keyup.enter事件绑定登录函数。很多同学做了登录按钮但鼠标操作习惯的人会直接按回车不加这个事件页面就不会有任何反应这在演示时非常尴尬。登录请求发出的代码比较简单const loginFormRef ref(null) async function handleLogin() { await loginFormRef.value.validate() const res await loginApi({ username: form.username, password: form.password }) localStorage.setItem(token, res.data.token) router.push(/dashboard) }注意token 不能放 sessionStorage要放 localStorage。因为用户关闭标签页后重新打开sessionStorage 会被清空用户就要重新登录localStorage 则能保持登录状态。4.3 Axios 拦截器设置与 token 注入接口请求都通过 Axios 封装。这里有两个拦截器必须配置好请求拦截器从 localStorage 里取出 token加到请求头。这样所有带 token 的接口都统一处理不需要每个请求都手写一遍Authorization字段。service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config })响应拦截器当后端返回 401token 过期、未登录时统一跳回登录页。同时把后端的业务错误信息用 Message 组件弹出提示。service.interceptors.response.use( response response.data, error { if (error.response?.status 401) { localStorage.removeItem(token) router.push(/login) } else { Message.error(error.response?.data?.message || 请求失败) } return Promise.reject(error) } )4.4 路由守卫和页面权限控制前端有一个非常关键的安全逻辑不能只靠后端拦截接口前端路由也要做守卫。如果用户未登录他在浏览器地址栏直接输入/dashboard应该被重定向到登录页。这个逻辑在 Vue Router 的beforeEach全局前置守卫里实现router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })管理员角色的后端接口我用的是/api/user/list前端也要配合管理员登录后显示用户管理菜单普通用户则不显示。判断依据是登录时后端返回的 token 里包含 role 字段前端在路由守卫里解析出来按角色控制菜单渲染。这部分虽小但能让你的项目有多角色权限的亮点可以讲。5. 跑通之后必须验证的边界情况我见过太多代码能跑但一演示就翻车的课程设计。根本原因不是功能没写而是没做边界测试。演示时老师往往不会按你准备好的剧本点很可能随手输入一个不存在的用户、或者点一下注册按钮连着点两次——这些场景你的代码抗不扛得住决定了演示效果。5.1 我实测下来的边界场景清单我把这个项目跑通后建议你至少对照下面的表格做一轮完整测试场景操作预期结果正常登录已注册账号 正确密码返回 token跳转首页密码错误已注册账号 错误密码提示用户名或密码错误用户不存在未注册的用户名提示用户名或密码错误不区分用户不存在重复注册相同用户名再次注册提示用户名已存在注册信息为空用户名或密码为空前端表单校验拦截不发请求token 过期2小时后访问用户信息接口后端返回401前端跳转登录页禁用账号登录status 为0的用户尝试登录提示该账号已被禁用SQL 注入用户名输入 OR 11无法登录MyBatis 参数化查询安全快速重复点击注册注册请求连点两次第二次返回用户名已存在依赖唯一索引兜底关于用户不存在和密码错误的提示我特意写成一个统一文案用户名或密码错误。这样做不是为了偷懒而是为了防止攻击者通过提示文案猜测系统里哪些用户已注册。这个细节在安全设计里叫用户枚举漏洞答辩时能主动提出来老师会高看你一眼。5.2 SQL 注入与 XSS答辩时的高频追问数据库课程设计答辩中SQL 注入是老师最可能问的安全问题之一。你需要能清楚地回答MyBatis 的#{}和${}有什么区别这个问题几乎必考。#{}是预编译参数占位符MyBatis 会把它转成 JDBC 的PreparedStatement占位符?参数值由数据库驱动处理不会参与 SQL 拼接所以能有效防止注入。${}是字符串拼接直接把值拼进 SQL 语句里存在注入风险一般只用于动态表名、动态排序字段等场景。前端能防止 SQL 注入吗不能前端任何校验都只是体验优化真正的安全防线在后端。这也是为什么我后端接口里仍然做了参数校验而不是完全相信前端。XSS 攻击在这个项目里更常见的场景是用户注册时在 nickname 字段输入scriptalert(xss)/script如果前端拿到后直接v-html渲染脚本就会执行。Vue3 默认插值{{ }}是转义的所以只要不滥用v-html就问题不大。你可以在答辩时主动说一句前端默认会转义特殊字符同时后端在写入前也做了字段长度和内容校验这样基本上就堵住了追问。5.3 数据库连接池与并发登录的小坑我在本地跑并发登录测试时发现如果同时发 20 个登录请求MySQL 默认连接数可能不够用。Spring Boot 默认的 HikariCP 连接池最大连接数是 10超过就得排队。你可以把配置调大一些spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5课程设计里连接池配置不是重点但如果你在答辩时能说出连接池的核心作用是复用数据库连接避免每次请求都创建新连接带来的性能开销就已经超出很多人的水平了。还有一个容易被忽略的坑是数据库连接中断。我遇到过同学演示时开着 Navicat、MySQL 服务、前端开发服务器、后端开发服务器结果某个服务忘了启动演示时白屏。强烈建议你演示前按照一套固定顺序启动服务先启动 MySQL再启动后端最后启动前端并在地址栏手动访问一下接口确认后端在线。6. 源码目录梳理与二次开发建议当你拿到这套完整源码之后建议不要急着直接运行而是先花十分钟把目录结构看懂。很多时候能跑和能改是两回事课程设计答辩考察的核心是后者。6.1 源码结构总览这里是我整理的一套目录结构你可以对照自己的项目来理解database-course-design/ ├── backend/ │ ├── src/main/java/com/example/dbdesign/ │ │ ├── controller/ # 接口层接收请求并返回结果 │ │ ├── service/ # 业务逻辑层事务控制 │ │ ├── mapper/ # MyBatis 数据访问接口 │ │ ├── entity/ # 数据库表对应实体类 │ │ ├── common/ # 统一返回结果类、异常处理 │ │ ├── config/ # 拦截器注册、跨域配置 │ │ └── interceptor/ # JWT 认证拦截器 │ └── src/main/resources/ │ ├── mapper/ # MyBatis XML SQL 文件 │ └── application.yml # 数据源与端口配置 ├── frontend/ │ ├── src/ │ │ ├── api/ # 后端接口请求封装 │ │ ├── views/ # 登录页、首页、用户管理页 │ │ ├── router/ # 前端路由与守卫 │ │ ├── utils/ # axios 封装、token 工具 │ │ └── App.vue │ └── package.json └── sql/ ├── db_design.sql # 建库建表脚本 └── init_data.sql # 初始化数据管理员账号等这套结构最大的特点是前后端完全分离同时 SQL 脚本独立存放。课程设计报告写结构设计时你可以直接把后端 controller/service/mapper 三层的职责抄进报告里再配上 SQL 脚本的注释说明非常省事。6.2 从能跑到会讲答辩前的准备清单代码跑通只是及格线。你可以按下面的清单检查自己是否具备答辩能力[ ] 能画出数据库 ER 图并说出每张表的主键、外键、唯一约束的作用[ ] 能解释用户表为什么用 BCrypt 而不是 MD5 存密码[ ] 能讲清 JWT 和 Session 的区别以及为什么选 JWT[ ] 能在数据库里手动执行一遍分页查询的 SQL并说出索引对排序的影响[ ] 能说明拦截器如何判断请求是否合法[ ] 能说出登录失败统一提示 vs 区分用户不存在各自的优缺点这七条是我每次模拟答辩都会问的基础题你如果能顺畅回答老师现场随机提问基本也问题不大。其中为什么用 BCrypt 而不是 MD5值得多讲两句。MD5 是摘要算法它不是为密码存储设计的相同密码生成的 MD5 完全一样配合彩虹表可以轻松反查出弱口令。BCrypt 是专门的密码哈希算法内部引入随机盐相同密码每次生成的哈希不同并且可以通过 cost 参数控制计算耗时提高了暴力破解的成本。只要盐值随机且强度够即使数据库泄露攻击者也很难从哈希反推出原始密码。这个知识点在课程设计答辩中属于安全设计亮点主动提出来非常加分。6.3 后续可以扩展的方向这套登录系统做完之后如果你想继续优化有四个方向性价比最高第一注册功能加图形验证码。用 Hutool 的验证码工具类生成图片后端缓存里存验证码值注册时校验。代码量不大但能额外展示缓存服务的使用。第二增加记住我功能。登录时勾选记住我token 有效期设为 7 天否则保持 2 小时。JWT 生成时动态设置过期时间即可实现。第三登录日志增加地理位置解析。日志表里已经存了 login_ip你可以用纯真 IP 库或者在线接口把 IP 解析成城市在日志列表页展示某用户从某地登录这个功能做出来视觉效果很直观。第四密码找回功能。通过邮箱验证码实现重置密码核心逻辑是生成一个短时有效的验证码验证通过后允许用户设置新密码。这个功能会涉及一定的表扩展验证码表也值得展示。我自己带完一届学生后发现凡是拿到这套源码后真正动手改过代码、加过功能的答辩成绩普遍比原样跑通的学生高一个档次。原因很简单老师一眼就能看出你是否真的理解了代码。哪怕你只是改了一个按钮的文字颜色、加了一个字段只要你讲得出改动的位置和原因在老师眼里这就是独立思考的信号。所以最后我建议你拿到源码先跑通跑通后挑一个功能动手改一改。改着改着你会发现原来那些抽象的概念——事务、索引、拦截器、token——全都变得具体了。这种感觉比你期末成绩单上的那个分数值钱得多。本文还有配套的精品资源点击获取
返回列表