Laravel Echo Server私有频道认证:无本地用户表实现方案咨询
适配无本地用户表的认证实现方案
1. 实现自定义无存储用户模型
首先创建不依赖本地数据库的用户认证模型,禁用写入操作:
// app/Models/AuthUser.php <?php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; class AuthUser extends Authenticatable { public $timestamps = false; // 字段和用户管理模块返回的用户字段对齐 protected $fillable = ['id', 'name', 'service_id']; // 重写save方法避免误写入本地数据库 public function save(array $options = []): bool { return true; } }
2. 注册自定义用户提供者
Laravel认证体系支持自定义用户源,直接对接用户管理模块即可,修改app/Providers/AuthServiceProvider.php的boot方法:
public function boot() { $this->registerPolicies(); // 注册自定义用户提供者 \Auth::provider('remote_user_provider', function ($app, array $config) { return new class implements \Illuminate\Contracts\Auth\UserProvider { // 按用户ID拉取用户 public function retrieveById($identifier) { $userInfo = $this->callUserModule('/user/get', ['user_id' => $identifier]); return $userInfo ? new \App\Models\AuthUser($userInfo) : null; } // 按凭证拉取用户 public function retrieveByCredentials(array $credentials) { if (empty($credentials['user_id'])) return null; $userInfo = $this->callUserModule('/user/check', ['user_id' => $credentials['user_id']]); return $userInfo ? new \App\Models\AuthUser($userInfo) : null; } // 校验凭证有效性 public function validateCredentials(\Illuminate\Contracts\Auth\Authenticatable $user, array $credentials): bool { // 你已经在消息提交环节校验过用户ID合法性,这里可直接返回true,也可再次调用接口确认 return true; } // 以下两个方法按需实现,不需要的话留空即可 public function retrieveByToken($identifier, $token) {} public function updateRememberToken(\Illuminate\Contracts\Auth\Authenticatable $user, $token) {} // 封装用户管理模块调用逻辑,可按实际情况换成直连用户模块数据库等方式 protected function callUserModule(string $path, array $params): ?array { $response = \Http::get('http://你的用户模块服务地址' . $path, $params); return $response->successful() ? $response->json() : null; } }; }); }
修改config/auth.php配置,启用自定义用户提供者:
'providers' => [ 'users' => [ 'driver' => 'remote_user_provider', ], ],
3. 替换原有全局登录逻辑
删除AppServiceProvider.php里临时生成测试用户的代码,改用中间件做动态认证:
首先创建认证中间件:
// app/Http/Middleware/RemoteAuthMiddleware.php <?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class RemoteAuthMiddleware { public function handle($request, Closure $next) { // 从请求中提取用户标识,消息提交接口取senderId,频道认证请求取携带的用户ID参数 $userId = $request->input('senderId') ?? $request->input('user_id'); if (!$userId) { return response()->json(['code' => 401, 'msg' => '缺少用户标识'], 401); } // 调用自定义提供者拉取用户并登录 $user = Auth::getProvider()->retrieveById($userId); if (!$user) { return response()->json(['code' => 403, 'msg' => '用户不存在'], 403); } Auth::login($user); return $next($request); } }
注册中间件到app/Http/Kernel.php:
protected $routeMiddleware = [ // 其他中间件保持不变 'remote.auth' => \App\Http\Middleware\RemoteAuthMiddleware::class, ];
将中间件挂载到需要认证的路由上:
// routes/api.php 消息提交接口挂载中间件 Route::post('/message/submit', [\App\Http\Controllers\MessageController::class, 'store'])->middleware('remote.auth'); // 广播认证路由挂载中间件,修改app/Providers/BroadcastServiceProvider.php public function boot() { Broadcast::routes(['middleware' => ['remote.auth']]); require base_path('routes/channels.php'); }
4. 适配私有频道认证
现在Auth门面已经可以正常拿到当前登录用户实例,直接写频道校验逻辑即可:
// routes/channels.php Broadcast::channel('user-{userId}', function ($user, $userId) { return $user->id == $userId; });
内容的提问来源于stack exchange,提问作者Kevin Mouen
相关产品推荐
相关产品推荐

