Laravel-Websockets 中使用 SSL

因为手头一个 ws 的项目必须 PWA 化,所以对应的 Websockets 也要使用 SSL,由于 Laravel-Websockets 文档中关于如何支持 SSL 写得不是很详细,把 issue 里面相关的问题都看了一遍最后才解决了,记录一下:yum:

  1. 生成证书(*.example.com)

    我使用的是 Let’s Encrypt 的免费通配符证书,生成步骤如下

    # 先确保你的机器上装了 git
    cd /opt
    git clone https://github.com/certbot/certbot.git
    cd certbot
    ./certbot-auto certonly --manual  --preferred-challenges=dns --email my@email.com --server https://acme-v02.api.letsencrypt.org/directory --agree-tos  -d *.example.com -d example.com

    然后按照提示为你的域名添加一个 TXT 的解析,用以验证你对域名的所有权,稍等片刻,让 DNS 缓存更新后验证成功即可生成 SSL 证书。

  2. 修改配置文件

    config/broadcasting.php

    <?php
    $ssl_pusher_config = [
     'driver' => 'pusher',
     'key' => env('PUSHER_APP_KEY'),
     'secret' => env('PUSHER_APP_SECRET'),
     'app_id' => env('PUSHER_APP_ID'),
     'options' => [
         'cluster' => env('PUSHER_APP_CLUSTER'),
         'encrypted' => true,
         'host' => '127.0.0.1',
         'port' => 6001,
         'scheme' => 'https',
         'curl_options' => [
             CURLOPT_SSL_VERIFYHOST => 0,
             CURLOPT_SSL_VERIFYPEER => 0,
         ]
     ]
    ];
    $not_ssl_pusher_config = [
     'driver' => 'pusher',
     'key' => env('PUSHER_APP_KEY'),
     'secret' => env('PUSHER_APP_SECRET'),
     'app_id' => env('PUSHER_APP_ID'),
     'options' => [
         'cluster' => env('PUSHER_APP_CLUSTER'),
         'encrypted' => true,
         'host' => '127.0.0.1',
         'port' => 6001,
         'scheme' => 'http'
     ]
    ];
    return [
     ...
     'connections' => [
         // 本地开发环境中不使用 SSL
         'pusher' => env('APP_ENV') === 'local' ? $not_ssl_pusher_config : $ssl_pusher_config,
         ...
     ],
    ];

    config/websockets.php

     ...
     'ssl' => [
         'local_cert' => env('SSL_CERT', null),
         'local_pk' => env('SSL_PK', null),
         'passphrase' => env('JWT_SECRET', null), // 这个是可选项,作用类似于 JWT_SECRET, 用于加密
         'verify_peer' => false,
     ],
     ...
  3. .env 相关配置

    BROADCAST_DRIVER=pusher
    ...
    PUSHER_APP_ID=appid
    PUSHER_APP_KEY=websocketkey
    PUSHER_APP_SECRET=secret
    ...
    SSL_CERT=/etc/letsencrypt/live/example.com/fullchain.pem
    SSL_PK=/etc/letsencrypt/live/example.com/privkey.pem
  4. 前端调用

    import Echo from 'laravel-echo';
    let echor = new Echo({
     broadcaster: 'pusher',
     key: process.env.MIX_PUSHER_APP_KEY,
     wsHost: window.location.hostname,
     wsPort: 6001,
     wssPort: 6001,
     disableStats: true,
     enabledTransports: ['ws', 'wss'],
     // 我用的是 jwt 进行验证的,如果你用的 session,请忽略此
     auth: {
         headers: {
             Authorization: `${store.state.auth.token.token_type}  ${store.state.auth.token.access_token}`
         }
     }
    });
    export default echor;
  5. 部署

    开放 6001 端口

    sudo ufw allow 6001

    让 websockets 持续运行,首先安装 supervisor

    apt install supervisor

    创建一个新的 supervisor 进程

    # 创建一个 websockets.conf
    touch /etc/supervisor/conf.d/websockets.conf
    # 填写如下
    [program:websockets]
    command=/usr/bin/php /your-project-location/artisan websockets:serve
    numprocs=1
    autostart=true
    autorestart=true
    user=sudo-www
    # 加载 websockets.conf
    supervisorctl update
    supervisorctl start websockets
    # 验证状态
    supervisorctl status

    完成~

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 5

不用这么麻烦的 .用nginx 转发一下就行了 nginx 那里配置ssl 证书.

3年前 评论

感谢楼主分享,这篇也可以参考

alex.bouma.dev/posts/installing-la...

3年前 评论

感谢楼主分享,不过按照上面的配置,最后还是提示无法连接websockets: file

使用的是宝塔环境,也是用supervisor建立进程,http协议下没有问题。 https折腾了好久也没实现,请教楼主可能是哪里出了问题呢?

1年前 评论
Yolver 1年前
feix0326 (作者) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!