韩雪峰 發表於 2019-6-4 03:05:00

小程序开发之搭建WebSocket的WSS环境(Apache+WorkerMan框架+PHP)

<p>这里我们用的是WorkerMan框架,服务器是CentOS,Web服务器是Apache,开发语言是PHP。</p>
<p>因为WSS是WebSocket和SSL的结合,所以需要提前准备好对应域名的SSL证书,一般情况下是三个证书文件,比如下面:</p>
<p>SSLCertificateFile "/www/wwwroot/test.crt"&nbsp;<br>SSLCertificateKeyFile "/www/wwwroot/test.key"&nbsp;<br>SSLCertificateChainFile "/www/wwwroot/test-ca-bundle.crt"</p>
<p>好,开始吧!</p>
<p>&nbsp;</p>
<p><strong>搭建可以端口访问的WSS协议长连接环境</strong></p>
<p>我以端口号39001(必须接入防火墙白名单)为例,代码如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:php;gutter:true;">&lt;?php
require_once __DIR__ . '/Workerman/Autoloader.php';
use Workerman\Worker;

// 证书最好是申请的证书
$context = array(

    'ssl' =&gt; array(
      // 请使用绝对路径
      'local_cert'               =&gt; '/www/wwwroot/test.pem', // 也可以是crt文件
      'local_pk'                   =&gt; '/www/wwwroot/test.key',
      'verify_peer'                =&gt; false,
      // 'allow_self_signed' =&gt; true, //如果是自签名证书需要开启此选项
    )
);
// 这里设置的是websocket协议(端口任意,但是需要保证没被其它程序占用)
$worker = new Worker('websocket://0.0.0.0:39001', $context);
// 设置transport开启ssl,websocket+ssl即wss
$worker-&gt;transport = 'ssl';
$worker-&gt;onMessage = function($con, $msg) {
    $con-&gt;send('ok');
};

Worker::runAll();
</pre>
</div>
<p>  </p>
<p>这样搭建完之后,Workerman就监听了端口为39001的wss协议,客户端就可以通过wss协议来连接workerman实现安全即时通讯了。</p>
<p>客户端的测试连接代码如下,可以通过打开chrome浏览器,按F12打开调试控制台,在Console一栏输入,或者把下面代码放入到html页面用js运行。</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> ws = <span style="color: rgba(0, 0, 255, 1)">new</span> WebSocket("wss://www.bojuwang.net:39001"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">2</span> ws.onopen = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 128, 128, 1)">3</span>   alert("WSS连接成功"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">4</span>   ws.send('伯驹网络'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">5</span>   alert("给服务端发送一个字符串:伯驹网络"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 0, 0, 1)">};
</span><span style="color: rgba(0, 128, 128, 1)">7</span> ws.onmessage = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e) {
</span><span style="color: rgba(0, 128, 128, 1)">8</span>   alert("收到服务端的消息:" + e.<span style="color: rgba(0, 0, 0, 1)">data);
</span><span style="color: rgba(0, 128, 128, 1)">9</span> };</pre>
</div>
<p>握手连接过程中如果出现404或者503的错误,一般是程序的问题,请自己检查。返回200说明整体连接成功。</p>
<p>这样我们就搭建了一个完整的WSS环境,可以使用了。但是小程序的WSS还比较特殊,因为它不允许使用443(SSL服务的默认端口)之外的端口,也就是我们只能使用这样的wss://www.bojuwang.net连接网址而不能使用这样带端口的wss://www.bojuwang.net:39001。这就需要我们使用Apache的代理服务,来解决这个问题。</p>
<p>&nbsp;</p>
<p><strong>搭建小程序WSS协议长连接环境(不带端口)</strong></p>
<p>首先,我们先创建监听39001的WebSocket,然后通过Apache代理将ws协议转为wss协议。</p>
<p>使用Workerman创建监听</p>
<div class="cnblogs_Highlighter">
<pre class="brush:php;gutter:true;">&lt;?php

require_once __DIR__ . '/workerman/Autoloader.php';
use Workerman\Worker;
use Workerman\Lib\Timer;

$ws_worker = new Worker("websocket://0.0.0.0:39001");

$ws_worker-&gt;count = 4;

// 当收到客户端发来的数据$data,处理之后发送给客户端
$ws_worker-&gt;onMessage = function($connection, $data)
{
   // 向客户端发送消息
    $connection-&gt;send('5,'.$data.',1');
};


// 运行worker
Worker::runAll();
</pre>
</div>
<p>  </p>
<p>这个时候我们使用上面的测试方法连接ws协议的网址是可以成功的,接下来将ws转换成wss。首先启用Apache的SSL连接配置以及代理模块,这一步非常重要,如果不启用的话,代理就无法生效。</p>
<p>具体启用方法找到apache的httpd.conf,启用代理模块,方法如下:</p>
<p>LoadModule proxy_module modules/mod_proxy.so<br>LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so</p>
<p><strong>然后启用SSL安全连接:</strong></p>
<p># Secure (SSL/TLS) connections<br>Include conf/extra/httpd-ssl.conf</p>
<p>具体的连接配置在这个httpd-ssl.conf文件中。然后我们找到httpd-ssl.conf文件进行如下配置:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:php;gutter:true;">Listen 443
&lt;VirtualHost *:443&gt;

# Proxy Config
SSLProxyEngine on
ProxyRequests Off

DocumentRoot "/www/wwwroot/"
ServerName www.bojuwang.net:443
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
SSLCertificateFile "/www/wwwroot/test.crt"
SSLCertificateKeyFile "/www/wwwroot/test.key"
SSLCertificateChainFile "/www/wwwroot/test-ca-bundle.crt"

&lt;Directory "/www/wwwroot/"&gt;
    AllowOverride All
    Require all granted
&lt;/Directory&gt;


ProxyPass / ws://0.0.0.0:39001
ProxyPassReverse / ws://0.0.0.0:39001
&lt;/VirtualHost&gt;
</pre>
</div>
<p>  </p>
<p>配置过程中监听端口不要重复,否则重启apache时会报错。</p>
<p>&nbsp;<img src="https://images2018.cnblogs.com/blog/281868/201808/281868-20180803121654792-2015925041.png"></p>
<p>各个代理路径证书路径也要注意,否则也会报错。</p>
<p><img src="https://images2018.cnblogs.com/blog/281868/201808/281868-20180803121737734-1962487677.png"></p>
<p>至此,大功告成!</p>
<p>这个时候服务器监听到443的SSL请求,就会代理到39001长连接端口,实现了WSS协议。</p>
<p>&nbsp;<img src="https://images2018.cnblogs.com/blog/281868/201808/281868-20180803122849739-153017701.png"></p><br><br>
来源:https://www.cnblogs.com/chbyl/p/10971249.html
頁: [1]
查看完整版本: 小程序开发之搭建WebSocket的WSS环境(Apache+WorkerMan框架+PHP)