# nobleLife 后台登录密码明文传输修复 — 知识库 > 服务器: aliyun (119.23.65.115) > 项目路径: `D:\wwwroot\nobleLife\backend\` > 框架: ThinkPHP 6 > 修复日期: 2026-06-29 > 修复范围: 后台管理登录页 `/admin/login/index` --- ## 一、问题描述 后台登录页提交时,用户输入的密码以明文形式出现在浏览器 Network 请求中,存在安全风险。 ## 二、修复方案 前后端同时改造:前端提交前对密码做摘要 → 后端只接收校验摘要值,全程不传原文。 ### 核心算法 ``` sha1( sha1('blog_') + md5(明文密码) + md5('_encrypt') + sha1(明文密码) ) ``` 输出为 40 位 hex 字符串(SHA1 标准长度)。 --- ## 三、修改文件清单 | 文件 | 操作 | 修改时间 | 说明 | |------|------|----------|------| | `public/static/js/login-crypto.js` | 新增 | 06-29 16:33 | 前端密码摘要库 | | `app/admin/view/login/index.html` | 修改 | 06-29 16:36 | 登录页引入 crypto、改写提交逻辑 | | `app/admin/controller/Login.php` | 修改 | 06-29 16:37 | 后端接收 password_hash | | `app/admin/model/AuthUser.php` | 未改 | — | 原逻辑直接兼容 | | `app/admin/common.php` | 未改 | — | 原 `password()` 函数算法一致 | --- ## 四、逐文件变更详情 ### 4.1 `public/static/js/login-crypto.js`(新增) 纯 JS 实现的 MD5 + SHA1 库,最终导出函数: ```javascript window.adminLoginPasswordHash = function (value) { value = String(value || ''); return sha1(sha1('blog_') + md5(value) + md5('_encrypt') + sha1(value)); }; ``` 不依赖任何第三方库,浏览器原生可用。 ### 4.2 `app/admin/view/login/index.html`(修改) **变更前:** ```javascript // 直接提交 data.field(含明文 password) $.ajax({ url: "{:url('login/loginHandle')}", method: 'post', data: data.field, ... }); ``` **变更后:** ```javascript var postData = $.extend({}, data.field); postData.password_hash = adminLoginPasswordHash(postData.password); delete postData.password; // ← 删除明文 $.ajax({ url: "{:url('login/loginHandle')}", method: 'post', data: postData, // ← 只含 password_hash ... }); ``` 同时 head 中新增引用: ```html ``` ### 4.3 `app/admin/controller/Login.php`(修改) **变更前:** ```php $pwd = trim($data['password'] ?? ''); ``` **变更后:** ```php $pwd = trim($data['password_hash'] ?? ''); // 新增格式校验:必须为 40 位 hex if (!empty($pwd) && !preg_match('/^[a-f0-9]{40}$/i', $pwd)) { return json(['code'=>'400','msg'=>'密码格式错误']); } ``` ### 4.4 `app/admin/model/AuthUser.php`(未改,原逻辑兼容) ```php public function getAdminByUsernamePassword($username, $password) { $result = Db::name('AuthUser')->where([ 'account' => $username, 'password' => $password // 直接对比 DB 中的 hash 值 ])->find(); return $result ?: false; } ``` DB 中 password 字段存储的就是 `password()` 函数的输出哈希,前端传的 hash 与之完全一致,无需改动。 ### 4.5 `app/admin/common.php`(未改,算法源头) ```php function password($value) { $value = sha1('blog_') . md5($value) . md5('_encrypt') . sha1($value); return sha1($value); } ``` 此函数用于创建/修改管理员时对密码做持久化存储,算法与前端 `adminLoginPasswordHash()` 一致。 --- ## 五、数据流对比 ``` 修复前: 用户输入密码 → form submit → Network 可见明文 "123456" 后端: 直接用 password 字段 修复后: 用户输入密码 → JS 本地摘要 → 提交 password_hash → Network 可见 40位hex 后端: 接收 password_hash → 格式校验 → 直接对比 DB hash ``` --- ## 六、验证方法 1. 打开浏览器 DevTools → Network 标签 2. 访问后台登录页,输入账号密码点击登录 3. 查看 loginHandle 请求的 Payload,确认只有 `password_hash` 字段(40位hex),无 `password` 明文 4. 登录成功后确认正常跳转后台首页 --- ## 七、注意事项 1. **不要删除 `app/admin/common.php` 中的 `password()` 函数** — 管理员创建/修改密码仍依赖它存储 hash 2. **不要删除 `public/static/js/login-crypto.js`** — 前端摘要依赖此文件 3. **此方案不是 HTTPS 替代** — 摘要传输可防止密码原文泄露,但不能防止重放攻击。生产环境建议同时启用 HTTPS 4. **API 端登录(`app/api/controller/Login.php`)未同步修改** — 小程序/App 端登录仍走原逻辑,如需修复需单独评估