Filament 使用外部数据库表进行用户认证终极指南
2025-03-10 02:16:54
Filament 使用外部数据库表进行用户认证
这问题挺常见,Filament 默认使用 Laravel 的 users
表进行认证。 但很多时候,我们需要用已有的用户表,还可能在不同的数据库里!这篇博客就来手把手教你如何配置 Filament,让它从另一个数据库的指定表读取用户信息进行登录验证。
问题根源
核心在于两点:一是 Laravel 的认证机制默认配置;二是 Filament 默认继承并使用了 Laravel 的这套认证体系。
- Laravel 认证配置: Laravel 默认的认证守卫(guard)和用户提供者(provider)配置通常指向本地数据库的
users
表。 相关的配置项位于config/auth.php
文件。 - Filament 用户模型: Filament 安装时会生成一个
User
模型(通常在app/Models
下),这个模型也默认与users
表关联。
解决方案:三步走
要让 Filament 从外部数据库的 usr
表认证,主要就三步:配置数据库连接、修改认证配置、调整 Filament 的用户模型。
1. 配置外部数据库连接
首先,得让 Laravel 能连上那个存着 usr
表的数据库。
打开 .env
文件,添加新的数据库连接信息。 假设外部数据库是 MySQL,那么像下面这样配置:
DB_CONNECTION_EXTERNAL=mysql
DB_HOST_EXTERNAL=192.168.0.31
DB_PORT_EXTERNAL=3306
DB_DATABASE_EXTERNAL=dbusers
DB_USERNAME_EXTERNAL=dbadmin
DB_PASSWORD_EXTERNAL=dbadmin@123
然后在 config/database.php
里,connections
数组中增加对应的连接配置:
'connections' => [
// ... 其他数据库配置 ...
'mysql_external' => [
'driver' => 'mysql',
'host' => env('DB_HOST_EXTERNAL', '127.0.0.1'),
'port' => env('DB_PORT_EXTERNAL', '3306'),
'database' => env('DB_DATABASE_EXTERNAL', 'forge'),
'username' => env('DB_USERNAME_EXTERNAL', 'forge'),
'password' => env('DB_PASSWORD_EXTERNAL', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
],
注意 :
* .env
中的配置项,其 DB_CONNECTION_EXTERNAL
是和这里数组的键 mysql_external
关联的, 自己要命名得对应上。
* 确保 MySQL 用户 dbadmin
具有从 Laravel 应用所在服务器访问 dbusers
数据库的权限。
2. 修改 Laravel 认证配置
接下来,修改 config/auth.php
文件, 让 Laravel 认证使用刚刚配置好的外部数据库和 usr
表。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'external_users', // 改这里,指向新的 provider
],
// ... Filament 可能还有其他 guard 配置,按需修改 ...
],
'providers' => [
'users' => [ //通常是 users
'driver' => 'eloquent',
'model' => App\Models\User::class, // 注意: 这行通常注释掉, 因为我们要重新定向provider
],
'external_users' => [ // 新增一个 provider
'driver' => 'database',
'table' => 'usr', // 外部数据库的表名
'connection' => 'mysql_external', // 指向第一步的数据库连接
],
],
解读:
guards.web.provider
:web
这个守卫现在使用名为external_users
的用户提供者。providers.external_users
: 这个自定义的提供者指定了:driver
:使用database
驱动 (直接查询数据库)。table
:使用usr
表。connection
: 使用'mysql_external' 连接
3. 调整 Filament 的 User 模型
有两种方法可以适配Filament用户模型,根据具体情况选用:
方法一: 重写 getUserByAuthIdentifier
(更推荐):
如果不想完全改变Filament获取用户的方式,只希望它使用不同的字段进行用户识别,可以在App\Models\User
模型(或者你自定义的与 Filament 用户相关的模型) 中重写 getUserByAuthIdentifier
方法:
// 在 app/Models/User.php (或者你自定义的用户模型) 中
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
// ... 其他代码 ...
protected $table = 'users'; //注意要根据实际修改
public function getUserByAuthIdentifier($identifier)
{
// 从外部数据中,使用给定的 userId 查找
return \DB::connection('mysql_external')->table('usr')->where('userId', $identifier)->first();
}
public function getAuthPassword()
{
// 'userPassword' 是密码的实际字段
return \DB::connection('mysql_external')->table('usr')->where('userId', $this->getAuthIdentifier())->value('userPassword');
}
/**
* 重新定义getAuthIdentifierName, 返回外部表的段。
* @return string
*/
public function getAuthIdentifierName()
{
return "userId";
}
// 其他的自定义逻辑和方法可以添加到这里
}
方法二:新建 User Model (彻底换模型):
如果你希望 完全 用 usr
表替换原来的 users
表,可以新建一个 User 模型:
-
创建新模型:
php artisan make:model ExternalUser
-
编辑
ExternalUser
模型 (app/Models/ExternalUser.php):<?php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; // 如果需要通知功能 class ExternalUser extends Authenticatable { use Notifiable; protected $connection = 'mysql_external'; // 使用外部数据库连接 protected $table = 'usr'; // 表名 protected $primaryKey = 'userId'; //主键名 public $incrementing = false; // 如果 userId 不是自增的 protected $keyType = 'string';//如果 userId 是字符串 protected $fillable = [ 'userId', 'email', 'userPassword', // 允许 mass assignment 的字段 ]; protected $hidden = [ 'userPassword', // 隐藏密码字段 ]; // 重写获取密码的方法 public function getAuthPassword() { return $this->userPassword; } /** * 重新定义getAuthIdentifierName, 返回外部表的关键字段。 * @return string */ public function getAuthIdentifierName() { return "userId"; } }
-
修改 Filament 配置:
打开
config/filament.php
(或者config/filament-panel.php
,取决于你的 Filament 版本),找到auth.user
或者 类似的配置项,改成:
注意:对于不同的版本可能存在差别,需要根据你所用的版本具体情况修改。'auth' => [ // ... 'user' => App\Models\ExternalUser::class, //改成新的model // ... ]
安全建议:
- 密码哈希: 绝对不要在数据库中明文存储密码! 确保
usr
表中的userPassword
字段存储的是哈希过的密码。 如果原系统没有哈希,强烈建议在迁移或同步数据时进行哈希处理(例如使用 Laravel 的Hash::make()
)。 - 最小权限原则: 数据库用户
dbadmin
只需要对dbusers
数据库的usr
表有必要的SELECT
权限就够了,不要给多余的权限。 - 数据库连接安全: 将数据库的配置写在
.env
文件中,然后把.env
文件添加到.gitignore
, 不提交到版本控制里。
进阶使用技巧:
如果需要登录时使用email做唯一校验,而不是userId
。 可以重写用户模型中的几个方法:
getAuthIdentifierName
改成return 'email';
。 然后, 再重写findForPassport
方法。
/**
* Passport 相关方法, 通过email寻找user
* @param $username
* @return mixed
*/
public function findForPassport($username) {
return $this->where('email', $username)->first();
}