# login-template **Repository Path**: creatywy/login-template ## Basic Information - **Project Name**: login-template - **Description**: 基于Java1.8和springboot2.7.18的登录页面,含前端加密及后端加密,及重置密码发送邮箱功能的示例项目 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-15 - **Last Updated**: 2026-02-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring Boot 安全项目模板 基于 Spring Boot 2.7.18 + Spring Security + MyBatis-Plus 的企业级安全项目,支持 WAR 包部署到 Tomcat。 ## 📋 目录 - [项目概述](#项目概述) - [技术栈](#技术栈) - [核心功能](#核心功能) - [密码加密方案](#密码加密方案) - [快速开始](#快速开始) - [项目结构](#项目结构) - [安全特性](#安全特性) - [密码重置功能](#密码重置功能) - [API 接口文档](#api-接口文档) - [常见问题](#常见问题) - [部署说明](#部署说明) - [安全检查清单](#安全检查清单) --- ## 项目概述 本项目是一个基于 Spring Boot 2.7.18 的企业级安全项目模板,集成了 Spring Security、MyBatis-Plus 和 Thymeleaf,提供了完整的用户认证与授权功能。 **适用场景:** - 企业级 Web 应用开发 - 需要安全认证的管理系统 - 学习 Spring Security 和 MyBatis-Plus 的参考项目 **项目特点:** - ✅ 完整的用户认证与授权体系 - ✅ 双重加密方案(AES 传输 + BCrypt 存储) - ✅ 完善的密码重置功能 - ✅ 已登录用户修改密码 - ✅ 邮件发送功能(支持降级处理) - ✅ 安全防护(CSRF、XSS、CSP) - ✅ 会话管理与并发控制 - ✅ 登录失败限制与账户锁定 --- ## 技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Spring Boot | 2.7.18 | 核心框架 | | Java | 1.8 | 开发语言 | | Spring Security | 5.7.x | 安全框架 | | MyBatis-Plus | 3.5.3.1 | 持久层框架 | | Thymeleaf | 3.x | 模板引擎 | | MySQL | 8.0.31 | 数据库 | | Lombok | 1.18.24 | 简化开发 | | JavaMail | Spring Boot Starter | 邮件发送 | --- ## 核心功能 ### 用户认证与授权 - ✅ 用户登录/退出 - ✅ 基于 Token 的会话管理 - ✅ 角色权限管理(ROLE_ADMIN、ROLE_USER) - ✅ 访问控制(URL 级别、方法级别) ### 密码安全 - ✅ **AES 前端加密 + BCrypt 后端存储** - ✅ 登录失败次数限制(5 次) - ✅ 自动账户锁定(30 分钟) - ✅ 密码强度验证(8 位,大小写字母 + 数字) - ✅ 密码重置功能(邮件发送) - ✅ **已登录用户修改密码** ✨ **新增** - ✅ 密码修改通知邮件 ### 安全防护 - ✅ CSRF(跨站请求伪造)防护 - ✅ XSS(跨站脚本)防护 - ✅ CSP(内容安全策略)配置 - ✅ 安全头部配置(X-Frame-Options、X-XSS-Protection 等) - ✅ 会话固定攻击防护 - ✅ 并发会话控制(最大 1 个会话) ### 密码重置 - ✅ 用户自助重置密码(通过邮件) - ✅ 管理员重置用户密码 - ✅ 一次性重置令牌(30 分钟有效期) - ✅ 邮件发送降级处理(开发环境控制台输出) - ✅ 密码修改通知邮件 ### 其他功能 - ✅ 操作日志记录 - ✅ 异常处理 - ✅ 错误信息脱敏 - ✅ 逻辑删除 --- ## 密码加密方案 ### 方案概述 本项目采用**可解密的 AES 对称加密**,实现了完整的"前端加密 → 后端解密 → 验证"流程。 ``` ┌─────────────────────────────────────────────────────────────┐ │ 数据库统一存储格式 │ │ BCrypt(原始密码) │ └─────────────────────────────────────────────────────────────┘ ↑ │ BCrypt 验证 │ ┌─────────────────────────────────────────────────────────────┐ │ CustomAuthenticationProvider │ │ │ │ 前端未加密 → 直接验证 BCrypt(明文) │ │ 前端启用加密 → AES 解密 → 验证 BCrypt(原始密码) │ └─────────────────────────────────────────────────────────────┘ ↑ │ 智能识别 │ ┌─────────────────────────────────────────────────────────────┐ │ LoginController │ │ 生成一次性 salt │ └─────────────────────────────────────────────────────────────┘ ↑ │ ┌─────────────────────────────────────────────────────────────┐ │ login.html │ │ 前端 AES 加密(可选) │ └─────────────────────────────────────────────────────────────┘ ``` ### 完整流程 ``` 1. 用户访问登录页 ↓ 2. 后端生成一次性 salt(AES 密钥) ↓ 3. 前端接收 salt ↓ 4. 用户输入密码,勾选"启用前端加密" ↓ 5. 前端用 AES 加密密码(密钥 = salt) ↓ 6. 前端发送加密数据:salt:Base64(密文) ↓ 7. 后端 CustomAuthenticationProvider 接收 ↓ 8. 智能识别:检测到加密格式(包含冒号) ↓ 9. 解析:salt = 前半部分,密文 = 后半部分 ↓ 10. 后端解密:AesEncryptionUtil.decrypt(密文, salt) ↓ 11. 得到原始密码 ↓ 12. 用 BCrypt(原始密码) 与数据库比对 ↓ 13. 数据库统一存储:BCrypt(原始密码) ``` ### 核心优势 1. ✅ **可解密加密**:AES 对称加密,后端可以解密 2. ✅ **一次性密钥**:每次登录生成新 salt,增强安全性 3. ✅ **随机 IV**:每次加密使用不同 IV,防止彩虹表攻击 4. ✅ **双重加密**:AES(传输)+ BCrypt(存储) 5. ✅ **统一存储**:数据库格式不受前端加密开关影响 6. ✅ **向后兼容**:支持前端加密开关平滑切换 ### 工作模式 #### 模式1:前端未加密(默认) **流程:** - 前端:传输明文密码 - 后端:BCrypt 验证 **数据库密码:** `BCrypt(admin123)` **优点:** 配置简单,无需前端加密 **缺点:** HTTP 环境下密码明文传输 **适用场景:** 开发测试环境 #### 模式2:前端启用加密 **流程:** - 前端:AES 加密 → `salt:Base64(密文)` - 后端:解密 → BCrypt 验证 **数据库密码:** `BCrypt(admin123)`(注意:与模式1相同) **优点:** 即使 HTTP 环境,密码也不会明文传输 **缺点:** 前端需要加载 aes-crypto.js **适用场景:** HTTP 环境的生产部署 --- ## 快速开始 ### 1. 环境要求 - JDK 1.8+ - Maven 3.6+ - MySQL 8.0+ - Tomcat 8.5+(生产环境) ### 2. 数据库配置 创建数据库并执行初始化脚本: ```sql -- 创建数据库 CREATE DATABASE IF NOT EXISTS template_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用数据库 USE template_db; -- 执行初始化脚本 SOURCE src/main/resources/sql/init.sql; ``` ### 3. 配置数据库连接 修改 `src/main/resources/application.properties`: ```properties # 数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/template_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource.username=root spring.datasource.password=your_password ``` ### 4. 配置邮件服务(可选,用于密码重置功能) 修改 `src/main/resources/application.properties`: ```properties # 邮件服务器配置(QQ 邮箱示例) spring.mail.enabled=true spring.mail.host=smtp.qq.com spring.mail.port=465 spring.mail.username=your_email@qq.com spring.mail.password=your_qq_smtp_auth_code spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.from=your_email@qq.com # 应用基础URL(用于生成重置链接) app.base-url=http://localhost:8080 ``` **获取 SMTP 授权码**: 1. 登录 QQ 邮箱 → 设置 → 账户 2. 开启"POP3/SMTP服务" 3. 生成授权码(不是邮箱密码) 4. 将授权码填写到 `spring.mail.password` **开发环境**:可以禁用邮件功能,重置链接在控制台输出: ```properties spring.mail.enabled=false ``` ### 5. 生成加密密码 **重要**:无论是否启用前端加密,数据库都统一存储 `BCrypt(原始密码)` 格式。 ```bash # 运行 BCrypt 加密工具类 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.PasswordUtil" ``` 工具类会生成: ``` === BCrypt 密码生成工具 === 数据库存储格式:BCrypt(原始密码) 前端加密(AES)仅用于传输保护,不影响数据库格式 用户: admin 原始密码: admin123 BCrypt密码: $2a$12$N9qo8uLOickgx2ZMRZoMy... SQL更新语句: UPDATE sys_user SET password = '$2a$12$N9qo8uLOickgx2ZMRZoMy...' WHERE username = 'admin'; ---------------------------------------- ``` 将生成的 BCrypt 密码更新到数据库。 **重要**:确保用户表中填写了 `email` 字段,否则无法发送密码重置邮件。 ### 6. 测试 AES 加密工具(可选) ```bash # 测试 AES 加密解密 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.AesEncryptionUtil" ``` ### 7. 编译运行 ```bash # 编译打包 mvn clean package # 运行 java -jar target/template-0.0.1-SNAPSHOT.war ``` 或部署到 Tomcat: ```bash # 将 target/template-0.0.1-SNAPSHOT.war 复制到 Tomcat webapps 目录 ``` ### 8. 访问应用 **开发环境**: - 首页(无需登录):`http://localhost:8080/` - 登录页面:`http://localhost:8080/login` - 管理后台(需要登录):`http://localhost:8080/admin` - 忘记密码:`http://localhost:8080/forgot-password` **生产环境(部署到 Tomcat /template 目录)**: - 首页(无需登录):`http://your-domain.com/template/` - 登录页面:`http://your-domain.com/template/login` - 管理后台(需要登录):`http://your-domain.com/template/admin` - 忘记密码:`http://your-domain.com/template/forgot-password` ### 9. 默认测试账号 | 用户名 | 密码 | 说明 | |-------|----------|------| | admin | admin123 | 管理员 | | test | test123 | 测试用户 | | user | user123 | 普通用户 | **⚠️ 重要提示:** 1. 首次使用前需要运行 `PasswordUtil` 生成加密密码并更新数据库 2. 确保用户表中填写了 `email` 字段,否则无法发送密码重置邮件 3. 生产环境请修改默认密码! --- ## 项目结构 ``` src/main/java/com/xxxx/template/ ├── config/ # 配置类 │ ├── SecurityConfig.java # Spring Security 配置 │ ├── LoginAttemptHandler.java # 登录尝试处理器 │ ├── MyBatisPlusConfig.java # MyBatis-Plus 配置 │ └── MetaObjectHandlerConfig.java # 元数据处理器 ├── controller/ # 控制器 │ ├── LoginController.java # 登录控制器 │ ├── PasswordResetController.java # 密码重置控制器 │ └── IndexController.java # 首页和管理后台控制器 ├── entity/ # 实体类 │ ├── User.java # 用户实体 │ └── BaseEntity.java # 基础实体 ├── mapper/ # MyBatis Mapper │ └── UserMapper.java # 用户Mapper ├── security/ # 安全相关 │ ├── CustomAuthenticationProvider.java # 自定义认证提供者 │ └── CustomPasswordEncoder.java # 自定义密码编码器 ├── service/ # 服务层 │ ├── CustomUserDetailsService.java # 自定义用户详情服务 │ ├── EmailService.java # 邮件服务接口 │ ├── PasswordResetService.java # 密码重置服务(接口) │ ├── UserService.java # 用户服务 │ └── impl/ # 服务实现 │ ├── BaseServiceImpl.java # 基础服务实现 │ ├── EmailServiceImpl.java # 邮件服务实现 │ ├── PasswordResetServiceImpl.java # 密码重置服务实现 │ └── UserServiceImpl.java # 用户服务实现 └── util/ # 工具类 ├── PasswordUtil.java # BCrypt 密码工具 └── AesEncryptionUtil.java # AES 加密工具 ``` **静态资源和模板:** ``` src/main/resources/ ├── static/ │ └── js/ │ └── aes-crypto.js # AES 加密工具 ├── templates/ │ ├── login.html # 登录页面 │ ├── forgot-password.html # 忘记密码页面 │ ├── reset-password.html # 重置密码页面 │ ├── reset-password-error.html # 重置链接无效页面 │ ├── index.html # 首页(无需登录) │ ├── admin.html # 管理后台(需要登录) │ ├── access-denied.html # 访问拒绝页面 │ └── emails/ # 邮件模板目录 │ ├── password-reset.html # 密码重置邮件模板 │ └── password-change-notification.html # 密码修改通知邮件模板 └── sql/ └── init.sql # 数据库初始化脚本 ``` --- ## 安全特性 ### 1. 密码安全 - ✅ 使用 BCrypt 算法加密存储密码(强度 12) - ✅ 前端使用 AES 对称加密传输 - ✅ 后端二次加密存储 - ✅ 密码长度和复杂度验证 - ✅ 密码强度实时提示 ### 2. 登录安全 - ✅ 登录失败次数限制(5 次) - ✅ 自动锁定账户(30 分钟) - ✅ 登录日志记录(用户名、IP、时间) - ✅ 防止暴力破解 - ✅ 会话管理(最大并发会话数 1) - ✅ 会话固定攻击防护 ### 3. 传输安全 - ✅ 前端 AES 加密传输 - ✅ CSRF 防护 - ✅ 安全头部配置 - ✅ CSP(内容安全策略) - ✅ XSS 防护 ### 4. 访问控制 - ✅ 角色权限管理 - ✅ 方法级权限控制 - ✅ URL 级别权限控制 - ✅ 403 访问拒绝页面 ### 5. 密码重置安全 - ✅ 一次性重置令牌(30 分钟有效期) - ✅ 令牌使用后立即失效 - ✅ 防止用户名枚举攻击 - ✅ 密码强度检查 - ✅ 邮件发送降级处理 - ✅ 密码重置后自动解锁账户 - ✅ 密码修改通知邮件 ### 6. 其他安全措施 - ✅ 逻辑删除 - ✅ 操作日志 - ✅ 异常处理 - ✅ 错误信息脱敏 --- ## 密码重置功能 ### ⚠️ 重要说明 **BCrypt 密码无法解密/反编译!** BCrypt 是单向哈希算法,设计上就不支持解密。这是安全设计的关键特性: - ✅ 只能加密,不能解密 - ✅ 防止彩虹表攻击 - ✅ 防止暴力破解 - ✅ 即使数据库管理员也无法获取用户的原始密码 ### 功能概览 #### 1. 用户自助重置密码 - 访问忘记密码页面 - 输入用户名 - 系统发送重置链接(邮件) - 点击链接设置新密码 - 密码重置成功后发送通知邮件 #### 2. 已登录用户修改密码 ✨ **新增** - 用户登录后可在管理后台修改密码 - 需要验证当前密码 - 实时密码强度检查 - 修改成功后自动退出登录 - 发送密码修改通知邮件 #### 3. 管理员重置密码 - 管理员可以为用户重置密码 - 可以生成临时密码 - 可以直接设置新密码 #### 4. 密码强度检查 - 最小长度:8 位 - 必须包含大写字母 - 必须包含小写字母 - 必须包含数字 #### 5. 邮件发送功能 - 支持发送密码重置邮件(HTML 邮件模板) - 支持发送密码修改通知邮件 - 使用 Thymeleaf 模板引擎渲染邮件内容 - 精美的邮件 UI 设计 - 支持 SMTP 配置(QQ、163、126 等邮箱) - 开发环境可选择禁用邮件,重置链接在控制台输出 ### 邮件配置 #### 配置 SMTP 服务器 编辑 `application.properties`: ```properties # 邮件服务器配置 spring.mail.enabled=true spring.mail.host=smtp.qq.com spring.mail.port=465 spring.mail.username=your_email@qq.com spring.mail.password=your_authorization_code spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.from=your_email@qq.com # 应用基础URL(用于生成重置链接) app.base-url=http://localhost:8080 ``` #### 常用邮箱 SMTP 配置 **QQ 邮箱**: ```properties spring.mail.host=smtp.qq.com spring.mail.port=465 spring.mail.username=your_email@qq.com spring.mail.password=your_qq_smtp_auth_code spring.mail.properties.mail.smtp.ssl.enable=true ``` **163 邮箱**: ```properties spring.mail.host=smtp.163.com spring.mail.port=465 spring.mail.username=your_email@163.com spring.mail.password=your_163_smtp_auth_code spring.mail.properties.mail.smtp.ssl.enable=true ``` **126 邮箱**: ```properties spring.mail.host=smtp.126.com spring.mail.port=465 spring.mail.username=your_email@126.com spring.mail.password=your_126_smtp_auth_code spring.mail.properties.mail.smtp.ssl.enable=true ``` #### 开发环境禁用邮件 ```properties # 禁用邮件功能(重置链接在控制台输出) spring.mail.enabled=false ``` **使用建议:** - ✅ **开发环境**:设置 `spring.mail.enabled=false`,重置链接在控制台输出 - ✅ **测试环境**:设置 `spring.mail.enabled=true`,使用测试邮箱 - ✅ **生产环境**:设置 `spring.mail.enabled=true`,配置正式的 SMTP 服务器 ### 使用方法 #### 用户自助重置密码 **1. 访问忘记密码页面** ``` http://localhost:8080/forgot-password ``` **2. 输入用户名** - 系统会生成重置令牌,有效期 30 分钟 - 查询用户的邮箱地址 - 发送密码重置邮件(如果 `spring.mail.enabled=true`) - 邮件发送失败或在控制台输出重置链接(测试环境) **3. 查看重置链接** **方式1:邮件接收(生产环境)** 用户会收到包含重置链接的邮件,邮件包含: - 美观的 HTML 格式 - 一次性的重置链接 - 链接有效期说明(30 分钟) - 安全提醒 **方式2:控制台输出(开发环境/测试)** ```bash ======================================== 密码重置链接(测试用): http://localhost:8080/reset-password?token=xxxxxx ======================================== ``` **4. 设置新密码** 访问重置链接,输入新密码并确认: - 新密码必须符合密码强度要求 - 两次输入的密码必须一致 - 密码重置成功后自动跳转到登录页 - 发送密码修改通知邮件 **5. 重置成功** - 密码已成功更新到数据库 - 解除账户锁定(如果有) - 重置失败次数为 0 - 发送密码修改成功通知邮件 #### 已登录用户修改密码 ✨ **新增** **1. 登录系统** ``` http://localhost:8080/login ``` **2. 访问管理后台** 登录成功后,系统会自动跳转到管理后台页面。 **3. 点击"修改密码"按钮** - 在用户信息区域找到"修改密码"按钮 - 点击后会弹出修改密码模态框 **4. 修改密码** 在模态框中填写: - **当前密码**:输入您当前的登录密码 - **新密码**:输入新密码(会实时显示密码强度) - 最小长度:8 位 - 必须包含大写字母 - 必须包含小写字母 - 必须包含数字 - **确认新密码**:再次输入新密码 **5. 提交修改** - 点击"确认修改"按钮 - 系统会验证: - 当前密码是否正确 - 新密码强度是否符合要求 - 两次输入的新密码是否一致 - 新旧密码是否相同 **6. 修改成功** - 显示成功提示消息 - 2 秒后自动退出登录 - 跳转到登录页面 - 发送密码修改通知邮件(如果配置了邮箱) **7. 重新登录** - 使用新密码登录系统 **注意事项**: - ⚠️ 修改密码后需要重新登录 - ⚠️ 建议定期修改密码以保障账户安全 - ⚠️ 密码修改成功后,所有其他设备的会话将失效 #### 邮件内容示例 **密码重置邮件**: ``` 🔐 密码重置请求 您好,admin! 我们收到了您的密码重置请求。如果这是您本人的操作,请点击下方的按钮重置您的密码: [重置密码] 或者复制以下链接到浏览器地址栏: http://localhost:8080/reset-password?token=xxxxxx ⚠️ 安全提醒: • 此链接仅有效 30 分钟 • 点击链接后,链接将立即失效 • 如果您没有请求重置密码,请忽略此邮件 ``` **密码修改通知邮件**: ``` ✅ 密码修改成功 您好,admin! 您的账户密码已成功修改! 修改时间:2024-01-15 10:30:00 ⚠️ 安全提醒: • 如果这是您本人的操作,请忽略此邮件 • 如果这不是您的操作,请立即联系系统管理员 • 建议定期更换密码以保障账户安全 ``` #### 管理员重置密码 **调用示例**: ```bash # 生成临时密码 curl -X GET "http://localhost:8080/api/admin/generate-temp-password?userId=1" # 直接设置新密码 curl -X POST "http://localhost:8080/api/admin/password-reset?userId=1&newPassword=NewPass123" ``` **控制台输出**: ``` ======================================== 【重要】临时密码(明文): AbCdEf12 请立即提供给用户,有效期仅一次 ======================================== ``` ### 技术实现 #### 核心类 - `EmailService` - 邮件服务接口 - `EmailServiceImpl` - 邮件服务实现 - `PasswordResetService` - 密码重置服务(包含 `changePassword` 方法) - `PasswordResetServiceImpl` - 密码重置服务实现 - `PasswordResetController` - 密码重置控制器(包含 `/api/user/change-password` 接口) - `UserService` - 用户服务(用于查询用户信息) #### 邮件模板 - `templates/emails/password-reset.html` - 密码重置邮件模板 - `templates/emails/password-change-notification.html` - 密码修改通知模板 #### 页面 - `forgot-password.html` - 忘记密码页面 - `reset-password.html` - 重置密码页面 - `reset-password-error.html` - 重置链接无效页面 - `admin.html` - 管理后台(包含修改密码功能) #### 安全特性 - ✅ 重置令牌有效期 30 分钟 - ✅ 令牌使用后立即失效 - ✅ 防止用户名枚举攻击(无论用户是否存在都返回成功) - ✅ 密码强度检查 - ✅ 邮件发送失败降级处理(控制台输出) - ✅ 密码重置后自动解锁账户 - ✅ 重置失败次数清零 - ✅ 密码修改通知邮件 - ✅ 已登录用户修改密码时验证当前密码 - ✅ 新旧密码不能相同 - ✅ 实时密码强度提示 - ✅ 修改密码后自动退出登录 --- ## API 接口文档 ### 认证接口 #### 1. 获取登录页面 ``` GET /login ``` - **描述**:显示登录页面 - **权限**:公开 - **响应**:HTML 页面 #### 2. 登录 ``` POST /api/auth/login ``` - **描述**:用户登录认证 - **权限**:公开 - **Content-Type**:`application/x-www-form-urlencoded` - **请求参数**: - `username`:用户名 - `password`:密码(可加密或明文) - `_csrf`:CSRF Token - **成功响应**:重定向到 `/admin` - **失败响应**:返回登录页面,显示错误信息 #### 3. 退出登录 ``` POST /api/auth/logout ``` - **描述**:退出登录 - **权限**:需要认证 - **请求参数**: - `_csrf`:CSRF Token - **成功响应**:重定向到 `/login?logout` ### 用户接口 #### 1. 获取当前用户信息 ``` GET /api/user/current ``` - **描述**:获取当前登录用户信息 - **权限**:需要认证 - **响应示例**: ```json { "success": true, "id": 1, "username": "admin", "realName": "管理员", "email": "admin@example.com", "phone": "13800138000", "authorities": ["ROLE_ADMIN"] } ``` #### 2. 修改密码 ``` POST /api/user/change-password ``` - **描述**:已登录用户修改密码 - **权限**:需要认证 - **Content-Type**:`application/x-www-form-urlencoded` - **请求参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | userId | Long | 是 | 用户ID | | oldPassword | String | 是 | 当前密码 | | newPassword | String | 是 | 新密码 | | confirmPassword | String | 是 | 确认新密码 | | _csrf | String | 是 | CSRF Token | - **成功响应**:`密码修改成功,请使用新密码重新登录` - **失败响应**:错误提示信息 ### 密码重置接口 #### 1. 请求密码重置 ``` POST /api/password-reset/request ``` - **描述**:申请密码重置 - **权限**:公开 - **请求参数**: - `username`:用户名 - **成功响应**:`密码重置链接已发送,请查收邮件(有效期30分钟)` - **失败响应**:`用户不存在或请求失败`(为了安全,用户不存在也返回相同提示) #### 2. 密码重置页面 ``` GET /reset-password?token={token} ``` - **描述**:显示密码重置页面 - **权限**:公开 - **响应**:HTML 页面(包含 token) #### 3. 重置密码 ``` POST /api/password-reset/reset ``` - **描述**:使用重置令牌修改密码 - **权限**:公开 - **请求参数**: - `token`:重置令牌 - `newPassword`:新密码 - `confirmPassword`:确认新密码 - **成功响应**:`密码重置成功,请使用新密码登录` - **失败响应**:错误提示信息 #### 4. 管理员重置用户密码 ``` POST /api/admin/password-reset ``` - **描述**:管理员重置用户密码 - **权限**:ROLE_ADMIN - **请求参数**: - `userId`:用户ID - `newPassword`:新密码 - **成功响应**:`密码重置成功` - **失败响应**:`密码重置失败` #### 5. 管理员生成临时密码 ``` GET /api/admin/generate-temp-password?userId={userId} ``` - **描述**:管理员为用户生成临时密码 - **权限**:ROLE_ADMIN - **请求参数**: - `userId`:用户ID - **成功响应**:`临时密码已生成并设置成功,请查看控制台日志获取明文密码` - **失败响应**:`生成临时密码失败` ### 页面路由 | 路由 | 方法 | 说明 | 权限 | |------|------|------|--------| | / | GET | 首页 | 公开 | | /login | GET | 登录页面 | 公开 | | /admin | GET | 管理后台 | 需要认证 | | /forgot-password | GET | 忘记密码页面 | 公开 | | /reset-password | GET | 重置密码页面 | 公开 | | /reset-password-error | GET | 重置链接无效页面 | 公开 | | /access-denied | GET | 访问拒绝页面 | 公开 | --- ## 常见问题 ### Q1: 为什么使用 AES 加密而不是 SHA-256? A: SHA-256 是单向哈希,无法解密,无法实现"前端加密 → 后端解密 → 验证"的流程。AES 是对称加密,可以解密,更适合传输保护场景。 ### Q2: 前端加密能完全替代 HTTPS 吗? A: 不能。前端加密只是额外的保护层,不能完全替代 HTTPS。HTTPS 提供了端到端的加密和身份验证,是更安全的解决方案。**生产环境强烈建议使用 HTTPS。** ### Q3: 如何在生产环境中使用? A: 生产环境必须: 1. 启用 HTTPS 2. 使用强密码策略 3. 定期更新依赖 4. 配置防火墙 5. 启用审计日志 6. 定期备份数据 ### Q4: 数据库存储什么格式的密码? A: 无论前端是否启用加密,数据库都统一存储 `BCrypt(原始密码)` 格式。前端加密仅用于传输保护,不影响数据库存储。 ### Q5: 如何添加新用户? ```bash # 1. 运行 PasswordUtil 生成加密密码 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.PasswordUtil" # 2. 在数据库中插入新用户 INSERT INTO sys_user (username, password, real_name, email, phone, create_time, update_time) VALUES ('newuser', '$2a$12$...', '新用户', 'user@example.com', '13800138000', NOW(), NOW()); ``` ### Q6: 如何修改用户密码? ```bash # 1. 运行 PasswordUtil 生成新密码的 BCrypt 值 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.PasswordUtil" # 2. 更新数据库 UPDATE sys_user SET password = '新的BCrypt密码' WHERE username = '用户名'; ``` ### Q7: 为什么不能从数据库恢复密码? A: BCrypt 是单向哈希算法,设计上就不支持解密。这是安全特性,不是 bug。密码丢失只能通过密码重置功能找回。 ### Q8: 管理员如何帮用户找回密码? A: 管理员可以重置密码(生成临时密码或设置新密码),但不能获取原始密码。 ### Q9: 重置令牌有效期多久? A: 30 分钟。过期后需要重新申请。 ### Q10: 密码强度要求是什么? A: 至少 8 位,必须包含大小写字母和数字。 ### Q11: 如何禁用邮件功能? A: 在 `application.properties` 中设置 `spring.mail.enabled=false`。此时重置链接会在控制台输出,适合开发测试环境。 ### Q12: 登录失败多少次后账户会被锁定? A: 连续失败 5 次后账户会被锁定,锁定时间为 30 分钟。 ### Q13: 如何修改账户锁定时间? A: 修改 `SecurityConfig.java` 中的 `MAX_ATTEMPTS` 和 `LOCK_TIME_DURATION` 配置。 --- ## 部署说明 ### 开发环境 ```bash # 直接运行 Spring Boot mvn spring-boot:run ``` ### 生产环境 #### 1. 打包为 WAR 文件 ```bash mvn clean package ``` #### 2. 部署到 Tomcat ```bash # 复制 WAR 包到 Tomcat webapps 目录 cp target/template-0.0.1-SNAPSHOT.war $TOMCAT_HOME/webapps/ ``` #### 3. 配置 Tomcat 编辑 `$TOMCAT_HOME/conf/server.xml`,确保以下配置: ```xml ``` #### 4. 启动 Tomcat ```bash $TOMCAT_HOME/bin/startup.sh ``` ### 部署清单 部署前请检查: - [ ] 修改默认测试密码 - [ ] 配置数据库连接 - [ ] 配置 SMTP 邮件服务(生产环境) - [ ] 启用 HTTPS(生产环境) - [ ] 配置防火墙规则 - [ ] 限制数据库访问 IP - [ ] 配置日志监控 - [ ] 设置密码策略 - [ ] 定期备份数据 - [ ] 更新依赖版本 - [ ] 审查用户权限 - [ ] 配置告警通知 --- ## 安全检查清单 ### 部署前检查 - [ ] 修改默认密码 - [ ] 启用 HTTPS(生产环境) - [ ] 配置防火墙规则 - [ ] 限制数据库访问 IP - [ ] 配置日志监控 - [ ] 设置密码策略 - [ ] 定期备份数据 - [ ] 更新依赖版本 - [ ] 审查用户权限 - [ ] 配置告警通知 ### 密码策略建议 - 最小长度:8 位 - 包含大小写字母、数字、特殊字符 - 定期更换密码(90 天) - 禁止使用弱密码 - 密码历史记录(禁止重复使用) ### 安全事件处理 #### 账户锁定 - 连续失败 5 次后自动锁定 - 30 分钟后自动解锁 - 管理员可手动解锁 #### 密码重置 - 需要邮箱验证 - 强度检查 - 令牌有效期 30 分钟 #### 安全告警 - 异常登录地点 - 多次登录失败 - 权限变更记录 --- ## 工具类说明 ### PasswordUtil - BCrypt 密码工具 **功能**: - 生成 BCrypt 加密密码 - 验证密码 - 检查密码强度 - 生成临时密码 **使用方法**: ```bash # 生成加密密码 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.PasswordUtil" # 生成临时密码 # 工具类会自动运行 main 方法生成临时密码 ``` ### AesEncryptionUtil - AES 加密工具 **功能**: - 生成一次性 salt - AES 加密 - AES 解密 **使用方法**: ```bash # 测试 AES 加密解密 mvn exec:java -Dexec.mainClass="com.xxxx.template.util.AesEncryptionUtil" ``` --- ## 参考文档 - Spring Security 文档:https://docs.spring.io/spring-security/reference/ - MyBatis-Plus 文档:https://baomidou.com/ - Spring Boot 文档:https://docs.spring.io/spring-boot/ - Thymeleaf 文档:https://www.thymeleaf.org/documentation.html --- ## 技术支持 如有问题,请参考: - Spring Security 官方文档 - MyBatis-Plus 官方文档 - Spring Boot 官方文档 - 本项目的 GitHub Issues(如果有) --- ## 许可证 本项目仅供学习和参考使用。