Как настроить авторизацию для подключения к серверу WebSocket Reverb (не к каналам, а именно к самому серверу)?

Я осваиваю новый стек технологий: <br/> Laravel 12 + Sanctum + Breeze (API) + Laravel Reverb (WS-сервер) на бэкенде, а на фронте использую Nuxt 3 и Pusher.js (без Laravel Echo). Все подключения происходят через API по токену, сессии не используются. Связка функционирует корректно на рабочем сервере. <br/><br/> У меня есть несколько требований: <br/> 1. Прежде всего, мне необходимо <b>ограничить доступ к WS-серверу (Reverb)</b>, чтобы разрешить подключение только авторизованным пользователям, например, по токену авторизации или дополнительному токену, генерируемому по запросу. <br/> 2. Также хочу <b>полностью отключить возможность подключения к публичным каналам</b>. <br/><br/> Почему это важно? Множественные подключения к WS представляют собой потенциальный риск для DDoS-атак.
  • 24 апреля 2025 г. 15:05
Ответы на вопрос 2
Чтобы настроить авторизацию для подключения к серверу WebSocket Reverb и ограничить доступ только авторизованным пользователям, а также отключить возможность подключения к публичным каналам, вам необходимо выполнить несколько шагов. Рассмотрим их подробнее.

### Шаги для настройки авторизации WebSocket в Laravel Reverb:

#### 1. Настройка Middleware для авторизации:

Создайте Middleware, который будет проверять токен авторизации перед подключением к WebSocket. В вашем случае, потребуется, чтобы Middleware проверял, соответствует ли токен, предоставленный клиентом, зарегистрированному пользователю.

```php
php artisan make:middleware WebSocketAuth
```

В созданном файле `app/Http/Middleware/WebSocketAuth.php` добавьте логику для проверки токена:

```php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class WebSocketAuth
{
    public function handle(Request $request, Closure $next)
    {
        $token = $request->header('Authorization');

        if (!$token || !preg_match('/Bearer (.+)/', $token, $matches)) {
            return response()->json(['message' => 'Unauthorized'], 401);
        }

        $user = Auth::guard('api')->user(); // проверка пользователя по токену
        
        if (!$user) {
            return response()->json(['message' => 'Unauthorized'], 401);
        }

        // Можно добавить дополнительные проверки, если нужно

        return $next($request);
    }
}
```

#### 2. Регистрация Middleware в `Kernel.php`:

После создания Middleware вам нужно зарегистрировать его в `app/Http/Kernel.php`, чтобы он мог быть использован для маршрутов.

```php
protected $routeMiddleware = [
    // Другие middleware
    'ws.auth' => \App\Http\Middleware\WebSocketAuth::class,
];
```

#### 3. Настройка роутов WebSocket:

Теперь вам нужно применить этот middleware к роутам вашего WebSocket-сервера. Это может быть сделано, например, в файле `routes/web.php` или в специальном файле для WebSocket. Вот пример использования:

```php
use Illuminate\Support\Facades\Route;

Route::middleware(['ws.auth'])->group(function () {
    // Ваши WebSocket роуты
});
```

#### 4. Отключение публичных каналов:

Если вы хотите полностью отключить возможность подключения к публичным каналам, вам нужно обеспечить, чтобы все каналы, к которым подключается клиент, были защищены. Один из вариантов — это не регистрировать публичные каналы в вашем канале WebSocket.

В файле `routes/channels.php` просто не создавайте публичные каналы, а проверяйте авторизацию пользователя в каналах, к которым хотите позволить доступ:

```php
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('private-channel.{id}', function ($user, $id) {
    // Логика проверки доступа к каналу
    return $user->id === (int) $id; // Например, доступ только для владельца
});
```

### Пример клиентского кода с Pusher.js:

Теперь, когда на сервере настроена авторизация, вам нужно использовать клиентскую библиотеку Pusher.js для подключения к WebSocket-серверу, передавая токен авторизации:

```javascript
import { Pusher } from 'pusher-js';

const pusher = new Pusher('<your-app-key>', {
  cluster: '<your-cluster>',
  wsHost: '<your-websocket-server>',
  wsPort: 6001, // укажите ваш порт
  forceTLS: false,
  authEndpoint: '/your-auth-endpoint', // ваш маршрут для авторизации
  auth: {
    headers: {
      Authorization: `Bearer ${yourAuthToken}`,
    },
  },
});

// Подписка на канал
const channel = pusher.subscribe('private-channel');
channel.bind('your-event', (data) => {
  console.log(data);
});
```

### Заключение

С помощью этих шагов вы сможете ограничить доступ к вашему WebSocket-серверу только авторизованным пользователям, а также отключить возможность подключения к публичным каналам. Убедитесь, что токены авторизации безопасны, и все каналы, к которым подключаются пользователи, объявлены в соответствии с вашей бизнес-логикой.
1 использовать wss 
2 перед подключением к ws серверу ходить по http в авторизованную зону и запрашивать для пользователя token с ttl, к токену сохранять ip адрес клиента (ну и айдишник пользователя в системе)
3 обращаться к ws каналу по пути wss://myhost/.../{token}/user_id
4 перед принятием соединения проверять что токен существует, относится к правильному пользователю, пришел с того же ip адреса
пысы как обрабатывать случаи когда один пользователь работает с устройств с разными ip решай сам, можно много вариантов придумать

так закроется общий доступ к ws серверу, не позволит сторонним лицам видеть чувствительную информацию

ws это потенциально эффективный ddos

а от ddos это не поможет. от ddos вот тут можно почитать Как защитить Websocket based сайт от DDoS атак?
Похожие вопросы