如何使用自定义身份验证方法向用户验证用户?
例如,在我的应用程序中,我为我的API使用了令牌身份验证(存储在每个用户的数据库中),通过标头传递并由自定义中间件读取。
如何使用这些自定义身份验证方法控制频道访问?如何成为客户端和服务器端?我使用的是socket.io,而且Laravel文档还不清楚auth方法如何适用于套接字。
使用案例
我将用户存储在DB中并使用默认的Laravel迁移。但是,我的应用程序只是API,它是无状态的,然后,我使用它来存储在登录端点中生成的唯一身份验证令牌,而不是使用remember_token
来存储会话令牌。
API的每个端点,请求都通过中间件,其中用户通过标头中的令牌检索用户
$token = Request::header('X-token');
$request->user = User::findByToken($token);
return $next($request);
现在问题出现了.Laravel docs对于私人渠道如何运作并不是很清楚。
广播客户端如何通过提及的令牌并获得加入指定频道的授权?
答案 0 :(得分:6)
Laravel documentation on broadcasting对此非常全面,虽然它没有详细介绍客户端库,但它并不支持开箱即用。
在这种情况下,您需要section on authorizing channels。来自文档:
在Laravel应用程序附带的
BroadcastServiceProvider
中,您会看到对Broadcast::routes
方法的调用。此方法将注册/broadcasting/auth
路由以处理授权请求
定义广播路由时,当前经过身份验证的用户将自动作为参数传递。由于您希望更改广播路由定义的提前的身份验证机制,以便传递正确的用户,因此您的广播客户端将传递令牌(无论您喜欢 - HTTP头, URL参数,POST数据等)然后您将自定义/broadcasting/auth
路由以解析该数据并使用它来验证用户。从那里,您将使用标准Broadcast::channel()
定义来确保经过身份验证的用户也是该频道上的授权用户。
根据文档,Broadcast::routes()
使用$attributes
的可选数组来使用web
中间件。来自the source:
$attributes = $attributes ?: ['middleware' => ['web']];
因此,如果您愿意,可以将中间件身份验证更改为'api'
,方法是将其传递给Broadcast::routes()
调用(或任何其他标准路由参数)。
自the route is already created for you以来,如果您想在路由功能/中间件的较低级别对其进行自定义,那么您需要更改auth()
方法,而不是BroadcastProvider
。使用。更具体地说,当路线设置时,它calls the authenticate()
method on the BroadcastController
,而calls the auth()
method on the Broadcast
facade只是a few providers defined out of the box。然后外观将调用您正在使用的任何提供商 - 如果您想编写自己的提供商,socket.io可以为您提供良好的起点。话虽如此,只要您没有提供商本身的问题,如果您需要某些内容,可能更容易编写自己的中间件并将其作为属性传递给Broadcast::routes()
特别是您的身份验证(如果它与api
身份验证中间件不同)。
另外,由于您已使用Laravel Echo对此进行了标记,因此您可能还需要阅读broadcasting introduction。还有socket.io
专门与{{3}}进行对话的部分。
答案 1 :(得分:1)
在Leith的答案之上,那些挠头的人想知道为什么创建自定义中间件并在BroadcastServiceProvider.php
中使用它会抛出错误。
public function boot()
{
Broadcast::routes(['middleware' => ['custom.middleware']]);
require base_path('routes/channels.php');
}
在Broadcaster.php
内部,有一种名为retrieveUser()
的方法,该方法应该return $request->user()
是自定义中间件内部成功进行身份验证的结果。
就我而言,我试图将access token
传递给API的自定义中间件;并且在对用户进行身份验证之后,我只是传递了原始请求return $next($request)
为使上述代码正常工作,我必须通过user
来获取access token
模型,然后像这样将其合并到原始请求中
$request->merge(['user' => $user ]);
$request->setUserResolver(function () use ($user) {
return $user;
});
return $next($request);
因此,retrieveUser()
中的Broadcaster.php
方法现在可以使用return $request->user()
命令检索经过身份验证的用户,并将其作为第一个参数传递给Broadcast::channel
方法
Broadcast::channel('private-channel-name', function ($user) {
// if you get here, you've been authenticated (within a custom middleware)
return true;
});
享受!