Laravel 5.8:如何实现数据库与Active Directory混合用户认证
嘿,我之前刚好在Laravel 5.8里折腾过类似的混合认证需求,给你梳理下具体的实现步骤,亲测可行:
整体思路
Laravel的认证系统本身是高度可扩展的,我们可以在默认的认证流程里加入分支逻辑:先尝试本地数据库用户认证,失败后再尝试Active Directory(AD)认证;对于首次通过AD验证的用户,自动将其信息导入本地数据库,后续登录时可以复用本地记录(也可以每次都校验AD密码,看你的需求)。
具体实现步骤
1. 安装AD认证依赖
Laravel生态里常用的AD集成包是adldap2/adldap2-laravel,注意要选适配Laravel 5.8的版本(v5.x系列),执行命令:
composer require adldap2/adldap2-laravel:5.2.*
然后发布AD的配置文件:
php artisan vendor:publish --provider="Adldap\Laravel\AdldapServiceProvider"
2. 配置AD服务器连接
打开生成的config/adldap.php文件,根据你的实际AD环境修改配置项:
'connections' => [ 'default' => [ 'auto_connect' => false, 'connection' => Adldap\Connections\Ldap::class, 'settings' => [ 'schema' => Adldap\Schemas\ActiveDirectory::class, 'account_prefix' => 'YOUR_DOMAIN\\', // 比如你的域是TEST,就填TEST\\ 'account_suffix' => '@your-domain.com', 'hosts' => ['ad.your-domain.com'], // AD服务器地址 'port' => 389, // 默认LDAP端口,用SSL的话改成636 'timeout' => 5, 'base_dn' => 'DC=your-domain,DC=com', // AD的基准DN 'username' => 'ad-admin@your-domain.com', // 有查询权限的AD账号 'password' => 'your-admin-password', ], ], ],
3. 自定义登录逻辑(核心)
我们需要重写默认的登录控制器逻辑,让系统支持双重认证路径。打开app/Http/Controllers/Auth/LoginController.php,添加/修改以下代码:
use Illuminate\Http\Request; use Adldap\Laravel\Facades\Adldap; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Str; // 重写认证方法 public function authenticate(Request $request) { // 先做登录参数验证 $this->validateLogin($request); // 第一步:尝试本地数据库用户认证 if (Auth::attempt($request->only('email', 'password'))) { return $this->sendLoginResponse($request); } // 第二步:本地认证失败,尝试AD认证 try { // 根据邮箱在AD中查找用户 $adUser = Adldap::search()->where('mail', '=', $request->email)->first(); // 验证AD用户的密码是否正确 if ($adUser && Adldap::auth()->attempt($adUser->getAccountName(), $request->password)) { // 检查本地数据库是否已有该用户记录 $localUser = \App\User::where('email', $request->email)->first(); if (!$localUser) { // 自动创建本地用户记录 $localUser = \App\User::create([ 'name' => $adUser->getCommonName(), 'email' => $adUser->getEmail(), // 生成随机密码占位(AD用户不会用到本地密码) 'password' => bcrypt(Str::random(16)), // 可选:添加标记字段区分AD用户和本地用户 'is_ad_user' => true, ]); } // 登录本地用户 Auth::login($localUser); return $this->sendLoginResponse($request); } } catch (\Exception $e) { // AD连接或验证失败,直接返回登录错误 return $this->sendFailedLoginResponse($request); } // 两种认证方式都失败,返回错误 return $this->sendFailedLoginResponse($request); }
4. 可选:添加AD用户标记字段
如果需要区分本地用户和AD用户,可以给users表加一个布尔字段:
- 生成迁移文件:
php artisan make:migration add_is_ad_user_to_users_table --table=users
- 编辑迁移文件:
public function up() { Schema::table('users', function (Blueprint $table) { $table->boolean('is_ad_user')->default(false); }); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('is_ad_user'); }); }
- 执行迁移:
php artisan migrate
5. 测试验证
- 本地用户:用之前注册的账号登录,应该正常进入系统;
- AD用户:用AD的邮箱和密码登录,第一次登录会自动在本地数据库创建用户记录,后续登录会自动完成认证。
关键注意事项
- 确保应用服务器和AD服务器网络连通,端口389(或636)开放;
- AD用户的邮箱字段要和本地用户的
email字段对应,如果AD里用的是其他标识(比如samaccountname),要调整代码里的搜索条件; - AD用户的本地密码只是占位,永远不会被使用,所以可以随便生成;
- 如果需要强制AD用户每次登录都校验AD密码(避免本地账号被篡改),可以修改逻辑,每次AD用户登录时都先验证AD密码,再登录本地用户。
内容的提问来源于stack exchange,提问作者ayobamilaye
相关产品推荐
相关产品推荐

