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:api
和 web
中间件的中间件。
喜欢我在这里发布的内容: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');
}
}
我正在使用 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:api
和 web
中间件的中间件。
喜欢我在这里发布的内容: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');
}
}