前言
最近在做 Excel 数据入库 MongoDB 的功能,整套架构是 ThinkPHP5.1 作为业务入口,调用 Python 服务解析 Excel 并写入 Mongo。上线联调遇到两个连续的坑:先是 PHP 侧报 Mongo 认证失败,改完配置后,又出现 Python 服务连接 Mongo 超时。踩坑过程有一定代表性,记录下来供遇到同类问题的同学参考。
环境简述
- MongoDB:7.0.43
- PHP 框架:ThinkPHP5.1,使用官方 think-mongo 驱动
- Python:pymongo 作为 Mongo 客户端
- 架构:PHP 业务层调用独立 Python 服务完成 Excel 解析入库
问题一:ThinkPHP 报 Authentication failed 认证失败
报错现象
AuthenticationException in Connection.php line 308
Authentication failed.
直接提示 Mongo 认证失败。
排查过程
- 先登录 Mongo 服务器,使用
mongosh手工测试账号登录,确认账号、密码本身无误。 - 查看用户定义:Mongo 用户创建在
admin认证库,账号拥有业务库读写权限。
use admin
db.getUsers()
关键点:MongoDB 用户是绑定在认证库的。很多人新建用户时,在 admin 库创建账号,连接时却没有指定
authSource=admin,就会认证报错。
- 配置坑:ThinkPHP5.1 的老版
think-mongo驱动不识别配置顶层直接写的 authSource。 ❌ 错误写法(很多人会这么写,不生效)
'mongo' => [
'type' => '\think\mongo\Connection',
'hostname' => 'xxx.xxx.xxx',
'database' => '业务库名',
'username' => 'mongo账号',
'password' => '账号密码',
'hostport' => '27017',
'authSource' => 'admin', // 放在顶层,老驱动读取不到!
],
✅ 正确写法:把认证参数放到params数组内
'mongo' => [
'type' => '\think\mongo\Connection',
'query' => '\think\mongo\Query',
'hostname' => '远程Mongo域名',
'database' => '业务库名',
'username' => 'mongo账号',
'password' => '账号密码',
'hostport' => '27017',
'params' => [
'authSource' => 'admin'
],
],
- 修改完成后,必须重启 php-fpm,PHP 配置存在缓存,不重启配置不生效。重启后 PHP 侧认证报错解决。
补充:Mongo7.0 默认使用 SCRAM-SHA-256 认证机制。如果后续还遇到认证异常,可以在 params 追加认证机制参数:
'params' => [
'authSource' => 'admin',
'authMechanism' => 'SCRAM-SHA-256'
],
问题二:PHP 侧修复后,Python 服务抛出连接超时
报错现象
调用导入接口返回 500,底层 Python 日志:
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017
问题定位
这个坑很容易被忽略:ThinkPHP 只是 HTTP 调用方,500 错误根源在 Python 后端。 Python 代码里面 Mongo 连接地址硬编码写死了127.0.0.1:27017,尝试访问 Python 服务器本机的 Mongo。 但是 Python 服务器并没有部署 Mongo 实例,本地端口没有服务,直接连接超时。
修复方案
修改 pymongo 连接串,指向远程 Mongo 实例,并且带上认证参数。 Mongo 连接 URI 模板:
mongodb://账号:密码@Mongo域名:27017/业务库?authSource=admin
Python 示例代码:
from pymongo import MongoClient
# 远程Mongo连接串,指定认证库
client = MongoClient("mongodb://账号:密码@Mongo域名:27017/业务库?authSource=admin")
db = client["业务库名"]
修改代码后,重启 Python 服务进程(uwsgi/gunicorn 等) 。
上线前网络校验
在 Python 服务器上,先测试端口连通性,确认网络策略放行 27017 端口:
nc -zv Mongo域名 27017
完整验证流程
- 调用 Excel 导入接口,传递文件地址参数;
- 观察 Python 服务日志,确认成功建立 Mongo 连接;
- 进入 Mongo 业务库,校验集合内数据是否正常写入。
踩坑总结
- MongoDB 认证核心规则:用户在哪一个库创建,authSource 就必须指定为哪个库,宝塔 / 云数据库默认在 admin 创建账号,极易踩坑。
- ThinkPHP5.1 think-mongo 老驱动限制:
authSource不能写在配置顶层,必须放到params数组,这个属于框架扩展的隐藏坑。 - 多服务架构联调,遇到接口 500,不要只看入口服务日志,要顺着调用链路,查看下游服务内部报错。本次一开始误判问题在 PHP,实际故障卡点在 Python 硬编码地址。
- 数据库连接信息不要硬编码写死在业务代码,推荐放到环境变量或者独立配置文件,方便多环境切换,同时降低信息泄露风险。
优化建议
- 安全层面:Mongo 安全组不要全开,只放行业务服务器的 IP 访问 27017 端口,缩小攻击面。
- 日志增强:Python 增加 Mongo 连接异常的详细日志,快速定位网络、认证类故障。
- 驱动版本:Mongo7.0 属于较新版本,PHP/Python 的 Mongo 客户端驱动尽量保持新版本,规避 SCRAM 认证兼容问题。
本文记录项目实战踩坑,希望帮你避开同样的坑。如果对你有帮助,欢迎点赞收藏,有问题评论区交流。