跳转至

4.3 开发基础:登录权限与第一个模块

沿着脚手架示例,完成第一个真实业务功能

第一个模块的目标不是做得多,而是完整走通

页面能够打开,只说明前端存在;接口能够返回,只说明后端存在。一个真正完成的业务模块,需要把数据库、业务逻辑、接口、页面、登录权限和验证连接起来。

本节先理解脚手架已有的登录权限,再仿照 DemoItem 示例完成一个范围小的业务模块。不要重新发明登录系统,也不要一次开发整条复杂业务流程。

本节学习目标

理解当前用户身份和角色如何从登录页面传递到后端业务接口,选择一个简单业务模块,按照“数据表 → 后端 → 接口 → 页面 → 权限 → 验证”的顺序完成开发。

返回上一节:改造工程 返回第四篇导读 进入下一节:完成业务


🎯 本节完成后,你要交付

成果 要求
登录权限验证记录 能说明登录状态保存在哪里,普通用户与管理员有什么差异
第一个业务模块 至少包含数据库、后端接口和可操作页面
模块接口说明 记录接口用途、角色、输入、成功结果和主要失败结果
模块测试记录 覆盖正常、未登录、无权限和输入错误中实际相关的场景
Git 提交记录 一个提交只完成一个可以解释和验证的小任务

本节完成的是一个相对独立的基础模块,例如图书查询、活动管理、报修提交或商品管理。跨角色流转、审批、借还和库存变化等完整业务流程留到下一节。


🧭 第一步:选定一个“小而完整”的模块

使用上一节形成的第一模块任务卡,再确认它适合作为首次开发任务。

推荐选择

项目类型 适合的第一个模块 可以验证什么
图书管理 图书列表、查询和维护 分页、条件查询、管理员操作
活动报名 活动列表和活动维护 页面展示、状态字段、角色权限
宿舍报修 报修项目或报修类型管理 基础数据、表单校验、管理权限
校园集市 商品分类或商品信息 图片之外的基础增删改查
预约管理 服务项目管理 时间、状态和输入校验

第一模块最好满足:

  • 对应一项已经确认的需求;
  • 只涉及一张核心表或少量简单关联;
  • 能够在一个页面完成主要操作;
  • 有明确的普通用户或管理员权限;
  • 一次课或一个小阶段能够验证;
  • 暂时不依赖复杂状态流转和第三方服务。

本节完成标准

1
2
3
4
5
6
7
用户登录
→ 打开业务页面
→ 页面调用真实接口
→ 后端校验身份、权限和输入
→ 业务逻辑读写数据库
→ 页面显示成功或失败结果
→ 刷新后数据仍然正确

不要把“第一个模块”理解成复制一套通用 CRUD

如果需求只允许管理员创建、普通用户只能查看,就不要为普通用户增加编辑和删除。功能、字段和权限必须来自自己的需求与系统设计。


🔐 第二步:理解并验证已有登录权限

两套脚手架已经提供登录、注册和当前用户查询。本节不重写这些基础设施,而是先理解业务模块怎样使用当前用户身份。

1
2
3
4
5
6
7
登录页面
→ POST /api/auth/login
→ 后端返回 JWT
→ Pinia 保存 token 和用户信息
→ Axios 请求头携带 Bearer token
→ JwtInterceptor 校验身份和角色
→ @CurrentUser 将当前用户交给业务接口

主要位置:

作用 位置
登录、注册、当前用户接口 backend/.../module/auth/
JWT 校验和角色检查 backend/.../security/
前端登录状态 frontend/src/stores/userStore.js
请求携带 Token frontend/src/api/request.js
页面路由权限 frontend/src/router/index.js
1
2
3
4
5
6
7
8
登录页面
→ POST /api/auth/login
→ 后端把用户写入 Session
→ 浏览器保存 Cookie
→ Fetch 自动携带 Cookie
→ LoginFilter 检查是否登录
→ AdminFilter 检查管理员角色
→ 业务 Servlet 从 Session 获取当前用户

主要位置:

作用 位置
登录、注册、退出、当前用户 controller/AuthServlet.java
登录检查 filter/LoginFilter.java
管理员页面检查 filter/AdminFilter.java
前端请求和 401 处理 src/main/webapp/js/common.js
登录页面 src/main/webapp/user/login.html

权限不只是一张页面

至少区分三件事:

检查 要回答的问题 示例
是否登录 系统知道当前是谁吗? 未登录不能查看个人记录
功能权限 当前角色能执行这个操作吗? 普通用户不能新增系统分类
数据权限 当前用户能操作这条数据吗? 用户只能修改自己提交的报修

页面隐藏按钮只能改善使用体验,不能代替后端校验。攻击者可以绕过页面直接调用接口。

先完成登录权限测试

场景 预期结果
正确账号登录 登录成功并能查询当前用户
错误密码 登录失败,不产生有效登录状态
未登录访问受限接口 返回 401 或明确的未登录结果
普通用户访问管理员功能 返回 403 或明确的权限不足结果
管理员访问管理功能 操作被允许
退出后再次访问 登录状态失效,需要重新登录

401 和 403 含义不同

401 表示尚未有效登录,403 表示已经识别身份但没有权限。页面可以给出不同提示,后端也应返回不同结果。


🔎 第三步:把 DemoItem 当作“路线图”

DemoItem 的价值不是业务内容,而是展示一个模块需要经过哪些层。先顺着示例代码走一遍,再创建自己的模块。

1
2
3
4
5
6
7
8
demo_item 表
→ DemoItem Entity
→ DemoItemMapper
→ DemoItemService
→ DemoItemController
→ frontend/src/api/demoItem.js
→ DemoItemList.vue / DemoItemForm.vue
→ router/index.js

新业务模块应放入:

1
2
3
4
5
6
7
backend/.../module/<业务名>/
├── entity/
├── mapper/
├── service/
├── service/impl/
├── controller/
└── dto/
1
2
3
4
5
6
7
demo_item 表
→ DemoItem Entity
→ DemoItemDao
→ DemoItemService
→ DemoItemServlet
→ common.js 的统一请求
→ demo-items.html / demo-item-form.html

新业务模块沿用:

1
2
3
entity → dao → service → controller
              HTML + JavaScript

阅读示例时回答

  1. 表字段怎样映射到 Java 对象?
  2. 输入对象和输出对象是否分开?
  3. “数据不存在”在哪一层判断?
  4. 接口怎样限制管理员操作?
  5. 页面怎样调用查询、新增、修改和删除接口?
  6. 登录失效后页面怎样处理?
  7. 分页参数和结果采用什么格式?

不要复制后再逐字替换。先理解每个文件承担什么职责,只复用结构和已有公共能力。


🗃️ 第四步:先完成数据和接口约定

开始写页面前,先确认数据表和接口。否则页面字段很容易与后端、数据库互相不一致。

数据表检查

字段 类型 必填 业务含义 校验或约束
id 【填写】 主键 自动生成
【业务字段】 【填写】 是 / 否 【填写】 【长度、范围】
status 【填写】 【填写】 【允许值】
created_at 【填写】 创建时间 自动记录

使用上一节建立的增量脚本创建或调整业务表。Spring Boot 路线继续追加新的 Flyway 迁移,不修改已经执行的 V1

接口清单

功能 方法与路径 角色 输入 成功结果 主要失败
分页查询 【填写】 【填写】 页码、条件 列表和总数 参数错误
查询详情 【填写】 【填写】 对象 ID 对象详情 数据不存在
新增 【填写】 【填写】 表单字段 新对象或成功结果 未登录、无权限、校验失败
修改 【填写】 【填写】 ID、表单字段 修改后结果 数据不存在、状态不允许
删除或停用 【填写】 【填写】 对象 ID 成功结果 无权限、对象正在使用

不是每个模块都必须有五个接口。根据真实需求删除不需要的操作,例如历史业务记录通常不应提供任意删除。


🧱 第五步:按后端分层逐步实现

建议按照“从数据库向接口”的顺序完成后端:

  1. 执行数据库脚本并检查表结构;
  2. 创建实体或数据对象;
  3. 完成数据访问;
  4. 完成业务逻辑和规则判断;
  5. 创建接口;
  6. 增加登录、角色和数据权限;
  7. 使用 Postman 或 Apifox 验证接口。

各层只负责自己的工作

层次 主要职责 不应承担
Entity 映射数据库字段 页面提示和复杂业务判断
DTO/VO 定义输入和输出 直接执行 SQL
Mapper/DAO 查询和修改数据库 判断用户能否操作
Service 业务规则、状态和数据权限 生成页面 HTML
Controller/Servlet 接收参数、调用服务、返回响应 堆积全部业务逻辑

当前用户不能来自前端信任

例如新增“我的报修”时,创建人应来自后端确认的当前用户:

正确:登录凭证 → 后端获得当前用户 ID → 写入业务数据
错误:前端提交 userId → 后端不校验直接写入

如果模块只有管理员维护,也要在后端接口校验管理员角色,而不是只隐藏页面按钮。

不要顺手修改公共基础设施

优先复用脚手架的统一响应、全局异常、JWT 或 Session、分页对象和数据库工具。确需修改 AGENTS.md 中的禁区文件时,先说明当前能力为什么不能满足需求、会影响哪些已有功能,并请教师确认。


🖥️ 第六步:完成页面和前后端连接

后端接口验证通过后,再完成页面。

页面至少包含

  • 页面标题和返回入口;
  • 查询条件或主要操作;
  • 列表、详情或表单;
  • 加载状态;
  • 空数据状态;
  • 成功或失败提示;
  • 根据角色显示的操作入口;
  • 输入校验;
  • 操作完成后的刷新或跳转。

两条技术路线

参考:

  • frontend/src/api/demoItem.js:封装业务请求;
  • frontend/src/views/demo/:列表和表单页面;
  • frontend/src/router/index.js:页面路由和前端访问控制;
  • Loading.vueEmpty.vuePagination.vue:公共组件。

新模块至少保持“API 文件、页面、路由”职责分开,不在 Vue 页面中重复创建一套 Axios 配置。

参考:

  • src/main/webapp/js/common.js:统一请求和错误处理;
  • src/main/webapp/admin/demo-items.html:列表和分页;
  • src/main/webapp/admin/demo-item-form.html:新增与编辑;
  • LoginFilterAdminFilter:后端访问控制。

使用现有 API.request(),不要在每个页面重复处理基础路径、Cookie 和 401 跳转。

先完成最小页面,再改善样式

第一轮只要求能够查询、输入、提交和看到结果。确认数据和权限正确后,再统一布局、颜色和交互细节。


🧪 第七步:用四类场景验证模块

不要只验证“管理员新增成功”。

1. 正常场景

  • 合法用户能够打开页面;
  • 查询结果与数据库一致;
  • 合法输入能够新增或修改;
  • 刷新页面后结果仍然存在。

2. 输入和数据场景

  • 必填字段为空;
  • 字符串过长或数值越界;
  • 查询不存在的 ID;
  • 重复数据违反唯一规则;
  • 空列表能够正常显示。

3. 登录和权限场景

  • 未登录直接访问页面或接口;
  • 普通用户直接调用管理员接口;
  • 用户修改参数尝试操作他人数据;
  • 退出登录后再次提交。

4. 运行和一致性场景

  • 前端提示与接口结果一致;
  • 接口字段与数据库字段一致;
  • 操作失败后数据库没有错误变化;
  • 后端日志没有新增异常;
  • 原有登录和 DemoItem 示例没有被破坏。

模块验证记录

场景 操作步骤 预期结果 实际结果 证据 结论
正常新增 【填写】 【填写】 【填写】 页面/接口/数据库 通过/未通过
未登录访问 【填写】 返回 401 【填写】 Network/接口 通过/未通过
普通用户越权 【填写】 返回 403 【填写】 接口响应 通过/未通过
输入错误 【填写】 明确提示,数据不变 【填写】 页面/数据库 通过/未通过

🤖 第八步:让 AI 一次完成一个小任务

不要直接要求:

帮我完成整个【项目名称】。

先让 AI 阅读现状并制定计划:

请先阅读 AGENTS.md、需求分析说明书、系统设计说明书,
以及 DemoItem 的数据库、后端、接口和页面代码。

本次只实现“【模块名称】”,对应需求【FR-*】。
使用角色:【填写】。
本次范围:【查询 / 新增 / 修改等】。
明确不做:【复杂流程、特色功能等】。

不要修改脚手架基础设施和无关模块。
请先输出:
1. 当前可复用的代码和结构;
2. 数据字段、接口和权限对应关系;
3. 分步任务清单;
4. 每一步准备修改的文件;
5. 正常、输入错误、未登录和越权验证方法;
6. 需要我确认的问题。

先不要修改文件。

确认方案后按小任务推进:

1
2
3
4
5
6
7
现在只完成第 1 步:【任务名称】。
完成后请运行对应检查,并说明:
1. 修改了哪些文件;
2. 为什么这样修改;
3. 执行了什么验证;
4. 实际结果是什么;
5. 还有哪些未完成内容。

如果出现错误,提供复现步骤、预期结果、实际结果、浏览器 Network 和后端日志,让 AI 先定位原因,不要让它连续尝试大量无依据修改。


👀 第九步:审查并提交

模块运行成功后,再做一次代码审查:

  • 是否符合需求和系统设计;
  • 是否复用脚手架已有结构;
  • 是否把业务逻辑堆在页面或 Controller;
  • 是否信任前端提交的用户身份;
  • 是否只有前端权限、缺少后端校验;
  • 是否处理数据不存在和输入错误;
  • 是否修改了无关文件或引入无用依赖;
  • 是否具有可复现的验证证据。

提交前执行适合当前路线的构建或测试,并检查改动:

git status
git diff

建议按小成果提交:

1
2
3
feat(<模块>): add database and backend API
feat(<模块>): add list and form pages
test(<模块>): cover permission and validation cases

提交信息可以使用中文,但必须说明完成了什么。不要把未完成页面、调试输出和无关格式调整混在同一个提交中。


✅ 本节验收清单

  • 第一个模块对应已确认需求;
  • 模块范围小,可以独立运行和验证;
  • 能说明 JWT 或 Session 怎样保存和传递登录状态;
  • 能区分登录、功能权限和数据权限;
  • 数据表和接口字段与系统设计一致;
  • 后端按职责完成数据访问和业务逻辑;
  • 当前用户身份由后端登录信息确定;
  • 管理操作具有后端角色校验;
  • 页面调用真实接口并读写数据库;
  • 页面具有加载、空数据和失败反馈;
  • 至少验证一个正常场景;
  • 至少验证一个输入或边界场景;
  • 未登录和越权操作得到正确拒绝;
  • 操作失败时数据库保持正确;
  • 原有登录和示例功能没有被破坏;
  • 已保存验证记录和范围清楚的 Git 提交。

📝 总结

  • 先理解登录链路:知道当前用户和角色怎样到达业务接口。
  • 沿示例完成纵向模块:从数据表一直做到页面和验证。
  • 权限以后端为准:页面隐藏按钮不能阻止越权调用。
  • 一次完成一个小任务:后端、页面和测试可以分步提交。
  • 完成必须有证据:页面、接口和数据库结果共同证明模块可用。

返回上一节:改造工程 进入下一节:完成业务