如何在Laravel Passport中通过Token手动认证WebSocket用户
Laravel WebSocket 自定义处理器的认证实现
根据你提供的代码,要完成WebSocket连接时的用户认证,你可以按照以下步骤实现:
1. 完善Token验证与用户获取逻辑
根据你项目使用的Laravel认证方案,选择对应的方式解析Token并获取用户:
情况一:使用Laravel Sanctum
如果项目用Sanctum处理API认证,可通过Token关联查询用户:
<?php namespace App\SocketServer; use App\Models\User; use Ratchet\ConnectionInterface; use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler; use Illuminate\Support\Facades\Auth; class SocketHandler extends WebSocketHandler { public function onOpen(ConnectionInterface $connection) { parent::onOpen($connection); $guzzleRequest = $connection->httpRequest; parse_str($guzzleRequest->getUri()->getQuery(), $getParameters); $token = $getParameters['token'] ?? null; if (!$token) { $connection->close(401, 'Token required'); return; } // 通过Sanctum Token哈希值匹配用户 $user = User::whereHas('tokens', function ($query) use ($token) { $query->where('id', hash('sha256', $token)); })->first(); if (!$user) { $connection->close(401, 'Invalid token'); return; } // 登录用户并绑定到连接属性 Auth::login($user); $connection->user = $user; } }
情况二:使用Laravel Passport
如果用Passport个人访问令牌,借助资源服务器验证Token:
<?php namespace App\SocketServer; use App\Models\User; use Ratchet\ConnectionInterface; use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler; use Illuminate\Support\Facades\Auth; use League\OAuth2\Server\ResourceServer; class SocketHandler extends WebSocketHandler { protected $resourceServer; // 依赖注入Passport资源服务器 public function __construct(ResourceServer $resourceServer) { $this->resourceServer = $resourceServer; } public function onOpen(ConnectionInterface $connection) { parent::onOpen($connection); $guzzleRequest = $connection->httpRequest; parse_str($guzzleRequest->getUri()->getQuery(), $getParameters); $token = $getParameters['token'] ?? null; if (!$token) { $connection->close(401, 'Token required'); return; } try { // 构造带Token的请求并验证 $request = $guzzleRequest->withHeader('Authorization', "Bearer {$token}"); $psrRequest = \Illuminate\Http\Request::createFromBase($request)->toPsrRequest(); $validated = $this->resourceServer->validateAuthenticatedRequest($psrRequest); $user = User::find($validated->getAttribute('oauth_user_id')); if (!$user) { throw new \Exception('User not found'); } Auth::login($user); $connection->user = $user; } catch (\Exception $e) { $connection->close(401, $e->getMessage()); return; } } }
情况三:自定义Token认证
如果是自己实现的Token逻辑(比如存在users表的api_token字段):
<?php namespace App\SocketServer; use App\Models\User; use Ratchet\ConnectionInterface; use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler; use Illuminate\Support\Facades\Auth; class SocketHandler extends WebSocketHandler { public function onOpen(ConnectionInterface $connection) { parent::onOpen($connection); $guzzleRequest = $connection->httpRequest; parse_str($guzzleRequest->getUri()->getQuery(), $getParameters); $token = $getParameters['token'] ?? null; if (!$token) { $connection->close(401, 'Token required'); return; } // 通过自定义Token字段查询用户 $user = User::where('api_token', $token)->first(); if (!$user) { $connection->close(401, 'Invalid token'); return; } Auth::login($user); $connection->user = $user; } }
2. 关键注意事项
- 不要直接抛出Exception,调用
$connection->close()返回错误码和信息,前端能明确捕获连接关闭原因。 - 将用户对象绑定到
$connection->user后,后续onMessage、onClose等方法可直接通过该属性获取当前连接的用户信息。 - 确保User模型已实现对应认证逻辑(比如Sanctum的
HasApiTokenstrait)。
内容的提问来源于stack exchange,提问作者Мохамед Русланович
相关产品推荐
相关产品推荐

