Nuxtjs + Laravel Echo + Laravel Passport + Laravel WebSockets 无法从私人/状态通道获取事件

Posted

技术标签:

【中文标题】Nuxtjs + Laravel Echo + Laravel Passport + Laravel WebSockets 无法从私人/状态通道获取事件【英文标题】:Nuxtjs + Laravel Echo + Laravel Passport + Laravel WebSockets can't get events from private/presence channels 【发布时间】:2020-04-26 14:11:23 【问题描述】:

我正在使用与 Laravel 后端分开托管的 NuxtJS。为了对用户进行身份验证,我使用 Laravel Passport。我正在尝试使用@nuxtjs/laravel-echopusher-js 为我的网站构建聊天功能。这是来自包beyondcode/laravel-websockets 的自托管websocket,使用php artisan websockets:serve 运行。例如,我使用了这个 repo https://github.com/qirolab/Laravel-WebSockets-Chat-Example。只有我使用 Laravel-Passport 和 NuxtJS 的区别

这是我的nuxt.config.js'buildModules` 部分

  buildModules: [
   ...
    [
      '@nuxtjs/laravel-echo',
      
        broadcaster: 'pusher',
        key: process.env.MIX_PUSHER_APP_KEY,
        cluster: process.env.MIX_PUSHER_APP_CLUSTER,
        encrypted: false,
        wsHost: process.env.WEBSOCKET_BASE_URL,
        wsPort: 6001,
        disableStats: true
      
    ]
  ],

  echo: 
    authModule: true,
    connectOnLogin: true,
    disconnectOnLogout: true
  ,

我在 Laravel (App\Events\ChatMessageSent.php) 中的活动如下所示:

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\ChatMessages;

class ChatMessageSent implements ShouldBroadcast

    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    public function __construct(ChatMessages $message)
    
        $this->message = $message;
    

    public function broadcastOn()
    
        return new PrivateChannel('chat.' . $this->message->room->id);
    

目前我没有过滤用户,所以我的channel.php 有这个条目:

.....
Broadcast::channel('chat.roomId', function ($user, $roomId) 
    return true;
);

并且该事件将被调度为(我现在没有使用..-&gt;toOthers()):

...
broadcast(new ChatMessageSent($message));
...

我的当前用户在我的 NuxtJS 应用程序中经过身份验证,可通过this.$auth.user 获得

在我拥有的前端文件中:

mounted:
  const channel = `chat.$this.roomID`
  this.$echo.private(channel).listen('ChatMessageSent', event => 
      console.log(
        '-------------------- This is happening!! -----------------------'
      )
      console.log(event)
      this.messages.push(event.message)
    )

但应用程序在所有 ChatMessageSent 事件上保持完全安静。根本没有控制台日志。如果我将其切换到公共频道,那么一切正常。我的猜测是身份验证有问题。 在websocket.php 配置文件中,我使用的是api 中间件

  */
    'middleware' => [
        'api',
        Authorize::class,
    ],

有没有办法在 websocket 上调试身份验证过程?

顺便说一句,我在调试控制台http://localhost:8000/laravel-websockets 中没有看到任何有关身份验证尝试的信息

【问题讨论】:

您可以使用推送仪表板dashboard.pusher.com > 频道 > 调试控制台。刷新您的页面,您应该开始看到其中出现的内容。您很可能会看到类似“连接”>“已订阅”>“已占用”的内容。 对不起,需要说明这是自托管的 websocket 在这种情况下,您可能需要更改您的nuxt.config.js,因为它具有推送器配置。 我基于github.com/qirolab/Laravel-WebSockets-Chat-Example 构建了这个。不同之处在于我使用的是 Laravel Passport 和 Nuxt.js。自托管推送器的选项在这里github.com/qirolab/Laravel-WebSockets-Chat-Example/blob/master/… 无法详细说明 laravel-websockets 的工作原理,但据我所知,它使用 pusher-js 的方式与使用 pusher.com 的方式相同,但只有你自己会使用包提供的websocket 【参考方案1】:

我很幸运找到了这篇文章https://medium.com/@mihkelallorg/laravel-react-jwt-tokens-and-laravel-echo-with-pusher-for-dummies-like-me-cafc5a09a1a1

要使上述方法起作用,第一步是(在 Laravel 方面) 在config/app.php 中取消注释App\Providers\BroadcastServiceProvider.php

'providers' => [    
    ...
    App\Providers\BroadcastServiceProvider.php,
    ...
]

然后我们需要稍微调整一下 App\Providers\BroadcastServiceProvider.php 以使用 API 身份验证。将Broadcast::routes() 替换为Broadcast::routes(['middleware' =&gt; ['auth:api']]);

public function boot()
    
        //Broadcast::routes();

        Broadcast::routes(['middleware' => ['auth:api']]);
        require base_path('routes/channels.php');
    

现在我们只需要在nuxt.config.js(NuxtJS 端)添加一行来指定 Auth 端点。我的BACKEND_BASE_URLhttp://localhost:8000 URL,由php laravel serve 提供

buildModules: [
    ....
    [
      '@nuxtjs/laravel-echo',
      
        broadcaster: 'pusher',
        key: process.env.MIX_PUSHER_APP_KEY,
        cluster: process.env.MIX_PUSHER_APP_CLUSTER,
        encrypted: false,
        wsHost: process.env.WEBSOCKET_BASE_URL,
        wsPort: 6001,
        disableStats: true,
        authEndpoint: process.env.BACKEND_BASE_URL + '/broadcasting/auth'
      
    ]
  ],

  echo: 
    authModule: true,
    connectOnLogin: true,
    disconnectOnLogout: true
  ,

现在私人频道正在使用自托管推送器

【讨论】:

【参考方案2】:

我在nuxt.config.js 中使用这个配置来工作:

buildModules: [
    ['@nuxtjs/laravel-echo', 
        broadcaster: 'pusher',
        key: process.env.WEBSOCKET_KEY,
        wsHost: process.env.WEBSOCKET_HOST,
        wsPort: process.env.WEBSOCKET_PORT,
        disableStats: true,
        forceTLS: true,
    ],
],

我们正在使用 443 端口的代理。

由于我们使用的是pusher,请确保您使用npm install --save pusher-js

.env

WEBSOCKET_KEY="hidden"
WEBSOCKET_HOST="notifications.example.com"
WEBSOCKET_PORT=443

但是,需要注意的是,我们的事件名称需要以 . 字符为前缀才能正常工作:

this.$echo.channel('orders')
    .listen('.TransactionStarted', (e) => 
        // action here
    )
    .listen('.TransactionCompleted', (e) => 
        // action here
    );

如果您有任何问题,请务必尝试在您的活动名称前加上 .

【讨论】:

以上是关于Nuxtjs + Laravel Echo + Laravel Passport + Laravel WebSockets 无法从私人/状态通道获取事件的主要内容,如果未能解决你的问题,请参考以下文章

使用 nuxtjs 登录 laravel sanctum 后出现 401(未验证)错误

在 nuxtjs 中刷新页面后如何保持用户身份验证?

我如何在我的 nuxt vps 上使用 laravel csrf 令牌

如何使用 NestJS GraphQL 实现 NuxtJS Apollo

使用 Nuxtjs 访问 Django api 时出现 CORS 错误 [重复]

带有参数的渴望加载 - laravel