Beego框架不内置LDAP认证,需手动集成;每次请求须新建LDAP连接并显式关闭,Bind须用管理员账号,查询过滤器需适配AD或OpenLDAP差异,登录流程必须重写Post方法接管认证链,实时校验用户状态。

Beego 框架本身不内置 SSO 或 LDAP 认证能力,必须手动集成 LDAP 客户端库并重写认证逻辑;直接复用 beego.Auth 或默认登录控制器会绕过 LDAP 校验,导致账号体系分裂。
LDAP 连接与 Bind 必须显式管理连接生命周期
Beego 是无状态 HTTP 框架,每次请求都新建 handler 实例,不能把 ldap.Conn 存在全局变量或结构体字段里长期复用——连接空闲超时、未关闭会导致 ldap: connection closed 错误,且并发下易出现连接泄漏。
- 每次认证请求都应调用
ldap.Dial("tcp", addr)建立新连接,defer conn.Close()确保释放 - Bind 必须使用管理员账号(
ldap_bindDN),不能用用户账号直连校验——多数 AD/LDAP 服务器禁止匿名 bind 后再 search,更不允许用户凭自己密码 bind 后查自己属性 - 连接地址建议从配置读取:
beego.AppConfig.String("ldap::ldap_server")+beego.AppConfig.Int("ldap::ldap_port"),避免硬编码 - 若启用了 LDAPS(端口 636),需额外调用
conn.StartTLS(&tls.Config{InsecureSkipVerify: false}),且证书必须可信,否则ldap: unable to start TLS
用户查询过滤器要适配 AD 和 OpenLDAP 差异
AD 默认用 sAMAccountName 存登录名,OpenLDAP 多用 uid;硬写 (uid=%s) 在对接 Windows 域控时必然查不到用户。
- AD 场景应改用:
fmt.Sprintf("(&(objectClass=user)(sAMAccountName=%s))", username) - OpenLDAP 或 FreeIPA 场景保持:
fmt.Sprintf("(uid=%s)", username) - 务必在
SearchRequest中指定需要返回的属性,如[]string{"sAMAccountName", "displayName", "mail", "distinguishedName"},否则sr.Entries[0].GetAttributeValue("displayName")会 panic - 查不到用户时,
len(sr.Entries) == 0是正常情况,不是错误;但len(sr.Entries) > 1表示过滤器太宽,需加objectClass限定,否则可能匹配到组织单元或服务账号
Beego 登录流程必须拦截默认行为并接管认证链
Beego 的 controllers.LoginController 默认只查本地数据库,不触碰 LDAP;若没重写 Post 方法,用户输域账号也能“登录成功”,但实际是创建了影子账号,后续密码变更、禁用等操作完全失效。
- 在
LoginController.Post中先调ConnLDAP(username)尝试获取用户信息 - 仅当
data != nil且utils.CompareHashAndPassword(data.UserPassword, inputPwd)成功时才视为 LDAP 认证通过(注意:AD 的userPassword不可读,应改用 bind 方式校验) - 推荐做法:用用户输入的密码对同一 DN 再做一次 bind,成功即认证通过,比解密比对更安全可靠
- 认证通过后,仍需调
models.BackendUserOneUserName查本地是否存在该用户;不存在则插入(同步基础字段),存在则更新最后登录时间——但绝不覆盖密码字段 - 调用
beego.GlobalSessions.SessionStart(c.Ctx.ResponseWriter, c.Ctx.Request)手动写入 session,并设置session.Set("username", username),后续中间件靠它判断登录态
最常被忽略的一点:LDAP 用户禁用(userAccountControl & 2 == 2 for AD,或 accountStatus=inactive for OpenLDAP)不会自动同步到 Beego 本地表;如果只依赖首次同步建库,后续 AD 中禁用的账号在 Beego 里仍能登录。必须在每次认证时实时检查用户状态字段,或定期跑同步任务更新 status 字段。


















