feat(ldap): 支持非邮箱用户名登录,完善 AD 兼容性

- 登录页放宽校验:登录模式允许任意账号格式,注册模式仍强制邮箱
- 登录属性新增 userPrincipalName 选项(AD 常用且通常是邮箱格式)
- LDAP 用户缺少邮箱属性时返回明确错误提示,替代误导性的"请输入正确的邮箱地址"
- LDAP 登录合并已有本地账号时记录 info 日志,便于审计

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kuaifan 2026-04-16 11:48:40 +00:00
parent e1c1fc030f
commit 1059630b9d
5 changed files with 18 additions and 4 deletions

View File

@ -2,6 +2,7 @@
namespace App\Ldap;
use App\Exceptions\ApiException;
use App\Models\User;
use App\Module\Base;
use App\Services\RequestContext;
@ -76,7 +77,7 @@ class LdapUser extends Model
public static function getLoginAttr(): string
{
$attr = Base::settingFind('thirdAccessSetting', 'ldap_login_attr');
return in_array($attr, ['cn', 'uid', 'mail', 'sAMAccountName']) ? $attr : 'cn';
return in_array($attr, ['cn', 'uid', 'mail', 'sAMAccountName', 'userPrincipalName']) ? $attr : 'cn';
}
/**
@ -201,10 +202,15 @@ class LdapUser extends Model
return null;
}
if (empty($user)) {
$email = self::getUserEmail($row) ?: $username;
$email = self::getUserEmail($row);
if (empty($email)) {
throw new ApiException('LDAP 用户缺少邮箱属性,请联系管理员配置');
}
$user = User::whereEmail($email)->first();
if (empty($user)) {
$user = User::reg($email, $password);
} elseif (!$user->isLdap()) {
info("[LDAP] merged with existing local account: userid={$user->userid}, email={$email}");
}
}
if ($user) {

View File

@ -973,3 +973,4 @@ AI 返回内容为空
此类型消息不支持转发
没有权限操作此任务
请选择要转发的消息
LDAP 用户缺少邮箱属性,请联系管理员配置

View File

@ -2360,3 +2360,4 @@ AI任务分析
请选择生日
登录属性
用于匹配登录用户名的 LDAP 属性Active Directory 请选择 sAMAccountName
请输入帐号

View File

@ -507,11 +507,16 @@ export default {
this.code = $A.trim(this.code)
this.invite = $A.trim(this.invite)
//
if (!$A.isEmail(this.email)) {
if (this.loginType == 'reg' && !$A.isEmail(this.email)) {
$A.messageWarning("请输入正确的邮箱地址")
this.$refs.email.focus()
return
}
if (!this.email) {
$A.messageWarning("请输入帐号")
this.$refs.email.focus()
return
}
if (!this.password) {
$A.messageWarning("请输入密码")
this.$refs.password.focus()

View File

@ -35,10 +35,11 @@
</FormItem>
<FormItem :label="$L('登录属性')" prop="ldap_login_attr">
<RadioGroup v-model="formData.ldap_login_attr">
<Radio label="uid">uid</Radio>
<Radio label="cn">cn</Radio>
<Radio label="uid">uid</Radio>
<Radio label="mail">mail</Radio>
<Radio label="sAMAccountName">sAMAccountName</Radio>
<Radio label="userPrincipalName">userPrincipalName</Radio>
</RadioGroup>
<div class="form-tip">{{$L('用于匹配登录用户名的 LDAP 属性Active Directory 请选择 sAMAccountName')}}</div>
</FormItem>