nobleLife_登录密码明文传输修复_知识库.md 4.6 KB

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 库,最终导出函数:

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(修改)

变更前:

// 直接提交 data.field(含明文 password)
$.ajax({
    url: "{:url('login/loginHandle')}",
    method: 'post',
    data: data.field,
    ...
});

变更后:

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 中新增引用:

<script type="text/javascript" src="__STATIC__/js/login-crypto.js"></script>

4.3 app/admin/controller/Login.php(修改)

变更前:

$pwd = trim($data['password'] ?? '');

变更后:

$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(未改,原逻辑兼容)

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(未改,算法源头)

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 端登录仍走原逻辑,如需修复需单独评估