如何使用Go-Fiber和MongoDB配置Go登录认证及修复登录接口panic问题
错误根源分析
- 全局
*mongo.Client变量未初始化。注册功能走的是dao.UserData封装的数据库操作,没有直接使用全局client,而登录函数直接调用client.Database,如果client为nil就会直接触发空指针panic,这是你看到SIGSEGV错误的核心原因。 - 登录逻辑变量赋值错误。你声明了
var user models.User但没有将请求解析到的data赋值给它,查询数据库用的user.Email是空值,后续密码比对用的user.Password也是零值,完全无法完成校验。 - 请求字段名不匹配。注册时取的密码字段是
data["password"],登录时写成了data["passwd"],永远拿不到正确的用户输入密码。 - 错误处理缺失。
FindOne查询出错后仅打印状态码,没有终止流程,后续逻辑会继续执行空值操作,也会触发panic。
解决方案
第一步:初始化全局Mongo客户端
确保程序启动阶段就完成Mongo连接初始化,给全局client变量赋值,示例初始化代码参考:
// 程序启动时调用该方法初始化Mongo连接 func InitMongo() error { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var err error client, err = mongo.Connect(ctx, options.Client().ApplyURI("你的Mongo连接串")) if err != nil { return err } // 测试连接可用性 return client.Ping(ctx, readpref.Primary()) }
如果你已经有dao层封装的数据库操作,建议登录也复用dao层的查询方法,避免直接操作全局client,减少空指针风险。
第二步:重写Login函数修正逻辑
修正后的完整登录函数如下:
func Login(c *fiber.Ctx) error { // 1. 解析请求参数 var data map[string]string if err := c.BodyParser(&data); err != nil { return err } // 校验必填参数 if data["email"] == "" || data["password"] == "" { c.Status(fiber.StatusBadRequest) return c.JSON(fiber.Map{ "message": "邮箱和密码不能为空", }) } // 2. 根据邮箱查询数据库用户 // 这里优先推荐复用dao层的查询方法,如果要直接用client请先确保client已初始化 collection := client.Database("Shashank").Collection("User") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // 必须释放context资源 var dbUser models.User err := collection.FindOne(ctx, bson.M{"email": data["email"]}).Decode(&dbUser) if err != nil { c.Status(fiber.StatusBadRequest) return c.JSON(fiber.Map{ "message": "用户不存在", }) } // 3. 比对密码 err = bcrypt.CompareHashAndPassword(dbUser.Password, []byte(data["password"])) if err != nil { c.Status(fiber.StatusBadRequest) return c.JSON(fiber.Map{ "message": "密码错误", }) } // 4. 登录成功返回用户信息(实际生产建议返回JWT token而不是完整用户信息,尤其是不要返回密码) dbUser.Password = nil // 清空密码字段再返回 return c.JSON(dbUser) }
内容的提问来源于stack exchange,提问作者S H A S H A N K
相关产品推荐
相关产品推荐

