【问题标题】:Laravel Broadcast - Combining multiple middleware (web, auth:api)Laravel Broadcast - 组合多个中间件(web、auth:api)
【发布时间】:2018-08-02 17:52:37
【问题描述】:

我正在使用 Laravel Event Broadcast 和 Pusher 在我的 API 和 Web 上使用 websocket。如果我单独尝试它们,两者都可以正常工作。我的意思是:

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


或者有没有一种方法可以为两者组合并创建一个混合中间件(本质上将检查 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..."

【问题讨论】:

    标签: laravel middleware laravel-5.5 laravel-passport laravel-events


    【解决方案1】:

    我终于想通了。

    我不确定这是否是实现这一目标的最佳方式,我非常感谢任何改进

    我实现的方法是为“网络”创建一个新的中间件,并将另一个留给它。步骤如下。

    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>
    

    【讨论】:

      【解决方案2】:

      我最好只使用扩展到auth:apiweb 中间件的中间件。

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

      【讨论】:

      • 但是,这种方法并没有返回我 auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..." 这是身份验证器所需要的
      【解决方案3】:

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

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

      【讨论】:

      • 很好的解决方案,我自己用过。尽管我必须将中间件指定为 'auth:api' 才能使其工作。谢谢!
      • @Sledmore 很高兴我能帮上忙!
      • 这似乎比我的解决方案更优雅。不过,我还没有亲自尝试过。
      【解决方案4】:

      广播服务提供者

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

      【讨论】:

        猜你喜欢
        • 2017-03-23
        • 2021-01-21
        • 2021-12-08
        • 2019-03-05
        • 2021-08-21
        • 2017-04-17
        • 1970-01-01
        • 2019-08-19
        • 1970-01-01
        相关资源
        最近更新 更多