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

7

我正在使用Laravel事件广播和Pusher来利用Websockets,既可以在我的API上使用,也可以在Web上使用。如果我分别尝试它们,两者都可以正常工作。我的意思是:

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')? 如果我想同时使用两个中间件,并且如果它通过一个中间件,它将绕过中间件。

请注意,我正在使用 Laravel Passport 作为我的 API。


还有一种方法可以将两个中间件组合并创建混合中间件吗 (这将基本上检查 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');

这将返回用户对象信息,然而,它应该返回像这样的内容:auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..."
5个回答

12
为什么不在BroadcastServiceProvider中使用类似这样的东西?这将创建两个单独的端点,并分配单独的中间件。
    Broadcast::routes(['middleware' => 'web']);

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

2
很棒的解决方案,我自己也用过。虽然我不得不将中间件指定为“auth:api”才能使其正常工作。谢谢! - Sledmore
1
@Sledmore 很高兴我能帮到你! - Alex Lacayo
2
这似乎比我的解决方案更优雅。不过我个人还没有尝试过它。 - senty

4
我最终想出了如何做到这一点。
我不确定这是否是实现此目标的最佳方法,如果有任何改进,我将非常感激。
我创建了一个新的 "web" 中间件,并将另一个中间件保留为原样。以下是步骤。
1)在BroadcastServiceProvider中,仅保留auth:api守卫以进行验证广播(Broadcast::routes(['middleware' => '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) 在我的routes>web.php中创建了一个独特的路由,而不是Laravel的/broadcasting/auth。

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

4) 然后我只在我的剑上使用它,使用方法如下:

<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>

1

但是,这种方法没有返回我需要的 auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8...",这正是认证器所需的。 - senty

0
广播服务提供程序
if (request()->hasHeader('authorization')){
    Broadcast::routes(['middleware' => 'auth:api']);
} else {
    Broadcast::routes();
}

0

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

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

你甚至可以为 Web 和 API 注册单独的服务提供者来分担责任,它将会奏效。对于 Web

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');
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接