Laravel 广播 - 组合多个中间件(网络,auth:api)

Laravel Broadcast - Combining multiple middleware (web, auth:api)

我正在使用 Laravel 事件广播和推送器在我的 API 和 Web 上使用 websockets。如果我单独尝试它们,两者都可以正常工作。我的意思是:

Broadcast::routes(['middleware' => 'web']); // this works for my Laravel website

Broadcast::routes(['middleware' => 'auth:api']); // this works for my api

但是,如果我想像这样同时使用两者:

Broadcast::routes(['middleware' => ['auth:api', 'web']]); // doesn't work

...两者都崩溃了,我怀疑这是假设我正在尝试为两个 auth:api && web 中间件启用。

有没有办法为此使用 OR 类型的语句(auth::api || 'web')?如果我想同时使用两者并且如果它通过一个中间件,它会绕过中间件怎么办。

请注意,我正在为我的 api 使用 Laravel 护照。


或者有没有办法为两者组合并创建一个混合中间件(这实际上会检查 api 或 web)?所以我可以使用这样的东西:

Broadcast::routes(['middleware' => 'broadcast']); // or auth:broadcast

更新:

据我了解,如果我创建一个名为 broadcast 的新中间件,我可以这样做:

class BroadcastMiddleware() {

  public function handle() {
    $web = Auth::guard('web')->user();
    if ($web) {
        return response()->json($web);
    }

    $api = Auth::guard('api')->user();
    if ($api) {
        return response()->json($api);
    }
    return response()->json('Unauthorized.', 500);
  }
}

但是我该如何更改 /broadcasting/auth 路线?如果我试试这个:

Route::post('/realtime/auth', function(){
    return true;
})->middleware('broadcast');

这 return 是用户对象信息,但是,它应该 return 类似于:auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..."

我终于知道怎么做了。

我不确定这是否是实现此目标的最佳方式,如果有任何改进,我将不胜感激

我如何实现的是为 'web' 创建了一个新的中间件,并保留了另一个。以下是步骤。

1) 在 'BroadcastServiceProvider' 中,Broadcast::routes(['middleware' => 'auth:api']); 只剩下 auth:api 个后卫。

这样,Laravel 的 auth:api 广播验证方法就如预期的那样工作了。

2) 创建了一个名为 "Broadcast" 的中间件并将其映射到 Kernel.php 中,如下所示:

'broadcast' => \App\Http\Middleware\Broadcast::class

Broadcast.php 中间件如下所示:

public function handle($request, Closure $next)
{
    $web = Auth::guard('web')->user();
    if ($web) {
        return response()->json(\Illuminate\Support\Facades\Broadcast::auth($request));
    }

    return response()->json('Unauthorized.', 500);
}

3) 在我的路线中创建了一条不同于 Laravel 的 /broadcasting/auth 的独特路线>web.php

Route::post('/guard/broadcast/auth', function(\Illuminate\Support\Facades\Request $req){
    return true;
})->middleware('broadcast');

4) 然后仅在我的 blade 上,我这样使用它:

<script>

let pusher = new Pusher("{{ env('PUSHER_APP_KEY') }}", {
    cluster: 'us2',
    encrypted: true,
    auth: {
        headers: {
            'X-CSRF-TOKEN': "{{ csrf_token() }}"
        }
    },
    authEndpoint: '{{ env('APP_URL') }}' + '/guard/broadcast/auth',
});

let channel = pusher.subscribe('private-channel.{{ Auth::user()->id }}');

channel.bind('my-event', addMessage);

function addMessage(data) {
    console.log(data);
}

</script>

我更喜欢只使用扩展到 auth:apiweb 中间件的中间件。

喜欢我在这里发布的内容:https://github.com/tlaverdure/laravel-echo-server/issues/266#issuecomment-365599129。所以,如果以后想改的话,我只维护了1个中间件

为什么不直接在 BroadcastServiceProvider 中使用这样的东西呢?这将创建两个单独的端点,并分配单独的中间件。

    Broadcast::routes(['middleware' => 'web']);

    Broadcast::routes(['prefix' => 'api', 'middleware' => 'api']);

广播服务提供商

if (request()->hasHeader('authorization')){
    Broadcast::routes(['middleware' => 'auth:api']);
} else {
    Broadcast::routes();
}

最好使用前缀方法来实现多种授权类型。 如果您将使用中间件 - 它只是多余的中间件。 如果您将使用 if 块(如下面的代码片段):您将面临路由缓存问题,它将 return 403 错误,因为 Laravel 应该使用一组中间件缓存路由。

if (request()->hasHeader('authorization')){
    Broadcast::routes(['middleware' => 'auth:api']);
} else {
    Broadcast::routes();
}

您甚至可以为 Web 和 api 注册单独的服务提供商以分担责任,这会奏效。 对于网络

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes(['middleware' => ['web']);

        require base_path('routes/channels.php');
    }
}

并且 Api

class ApiBroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes(['prefix' => 'api', 'middleware' => ['auth:api']]);

        require base_path('routes/dam-channels.php');
    }
}