【问题标题】:Laravel Broadcast authenticationLaravel 广播认证
【发布时间】:2018-04-13 22:36:24
【问题描述】:

如何使用自定义身份验证方法对频道的用户进行身份验证?

例如,在我的应用程序中,我为我的 API 使用令牌身份验证(存储在每个用户的数据库中),通过标头传递并由自定义中间件读取。

如何使用这些自定义的频道身份验证方法控制访问?客户端和服务器端如何?我正在使用 socket.io 并且 Laravel 文档非常不清楚 auth 方法如何用于套接字。

用例:

我使用默认 Laravel 迁移将用户存储在数据库中。但是,我的应用程序如何只是 API,它是无状态的,然后,我没有使用 remember_token 来存储会话令牌,而是使用它来存储在登录端点中生成的唯一身份验证令牌。

API 的每个端点,请求都通过一个中间件,在该中间件中,用户通过标头中存在的令牌检索

$token = Request::header('X-token');

$request->user = User::findByToken($token);

return $next($request);

现在问题来了。Laravel 文档对私有通道的工作方式不是很清楚。

广播客户端如何传递上述令牌并获得授权加入给定频道?

【问题讨论】:

  • 嘿@Luiz 我仍然不确定你想弄清楚什么?
  • 如果我不使用 Laravel 默认的身份验证方法(例如,JWT 或其他令牌方法),我想知道如何授权用户访问给定的私人频道。
  • @Luiz 您能否提供一些代码示例来说明您已经尝试过的内容以及您认为缺少知识的地方?
  • @Leith 当然,更新了问题

标签: php laravel socket.io


【解决方案1】:

Laravel documentation on broadcasting 对此非常全面,尽管它没有详细介绍它不支持开箱即用的客户端库。

在这种情况下,您需要section on authorizing channels。来自文档:

在 Laravel 应用程序中包含的 BroadcastServiceProvider 中,您将看到对 Broadcast::routes 方法的调用。该方法会注册/broadcasting/auth路由来处理授权请求

在定义广播路由时,当前经过身份验证的用户会自动作为参数传递。由于您希望更改广播路由定义的身份验证机制 ahead 以便传递正确的用户,因此您的广播客户端将传递令牌(但是您喜欢 - 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,如果您想在路由函数/中间件的较低级别对其进行自定义,那么您需要更改您正在使用的BroadcastProvider 上的auth() 方法。更具体地说,当设置路由时,它是calls the authenticate() method on the BroadcastController,而这又是简单的calls the auth() method on the Broadcast facade。然后,外观会调用您正在使用的任何提供程序 - 如果您想编写自己的代码,a few providers defined out of the box 应该会给您一个很好的起点。话虽这么说,只要您对提供程序本身没有问题,如果您需要特定的身份验证(如果它不同来自api 身份验证中间件)。

另外,由于您已将其标记为 ,因此您可能还需要阅读 Laravel Echo。在broadcasting introduction 中还有一个关于与socket.io 交谈的部分。

【讨论】:

  • 是的,我见过 Echo。但是如果我不能使用 Echo 或者我在客户端使用另一种语言而不是 JavaScript 怎么办?无论如何。关于这部分:“在定义广播路由时,当前经过身份验证的用户作为参数自动传递”它似乎仅适用于 Web 身份验证用户,而不适用于 API 用户。关于“然后您将自定义 /broadcasting/auth 路由以解析该数据并使用它来验证用户”尚不清楚。我会为此创建一个路由和控制器吗?这将接收和返回什么?进程何时调用此路由?
  • @Luiz 用更具体的细节和对 Laravel 源的引用更新了我的答案。你用什么客户端来消费它并不重要,如果你没有看到它,关于 Echo 的注释只是为了感兴趣而添加的。您可能只需要调整传递给Broadcast::routes() 的中间件即可使用您的api 身份验证。
【解决方案2】:

除了 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)

为了使上述代码正常工作,我必须通过access token 获取user 模型,然后像这样将其合并到原始请求中

$request->merge(['user' => $user ]);

$request->setUserResolver(function () use ($user) {
    return $user;
});

return $next($request);

所以现在Broadcaster.php 中的retrieveUser() 方法能够使用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;
});

享受吧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-06
    • 2019-12-22
    • 2017-11-07
    • 2023-03-17
    • 2018-07-14
    • 2021-05-26
    • 2023-03-04
    • 2018-12-03
    相关资源
    最近更新 更多