websocket使用ssl链接不上服务器(已解决)

阅览了cocos creator相关issue,仍然没有解决问题

问题描述: websocket使用wss协议链接不上服务器

环境: 操作系统win7, cocos creator 1.8.2 版本

新建空项目的测试用的代码:
var ws = new WebSocket("wss://h5.zltianhen.com/uc", "whmj", cc.url.raw("resources/DSTRootCAX3.crt")); ws.onopen = function (evt) { console.log("onopen"); alert("success"); } ws.onerror = function (evt) { console.log("onerror"); console.log(evt); alert("error"); } ws.onclose = function (evt) { console.log("onclose"); console.log(evt); alert("onclose"); }

浏览器效果: 链接成功,弹出onopen
编译成ios包的效果: 链接成功
编译成android包的效果: 链接失败

我自己对于问题所做的工作:

猜测1: 是否是服务器的原因导致?
操作1: 使用浏览器链接服务器,成功。
操作2: 使用ios包链接服务器,成功。
结论: 服务器的websocket处理是符合websocket标准协议的

猜测2: 是否是安卓的websocket库导致的?
操作1: 使用 new WebSocket("wss://echo.websocket.org") 方式链接别人的websocket 服务器,成功
结论: 安卓包甚至都不需要导入ca 文件都能成功,看来安卓库也不一定有问题,换个思路

猜测3: ca root文件有问题?
操作: 打开浏览器,访问我们的服务器网站,查看证书,选择详细信息labelbox,复制证书,导出证书,确认内容,内容和原先的一样
结论: ca证书没有问题

猜测4: 证书格式有问题?
操作:导出 cer二进制文件来使用,不行。
结论:看来不是二进制

猜测5: 导出的base64编码的cer证书后缀名有问题?
操作 : 到浏览器导出cer二进制文件,使用openssl生成pem后缀文件,发现pem和base64编码的cer文件一样
结论: 证书没有问题

报错内容:
05-14 15:06:18.992 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: scheme: wss, host: h5.zltianhen.com, port: 0, path: /uc 05-14 15:06:18.992 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: CA file (/data/data/com.bailing.MoneyGuest/files/DSTRootCAX3.pem) in writable path exists! 05-14 15:06:18.992 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: NOTICE: Creating Vhost 'default' port -1, 1 protocols, IPv6 on 05-14 15:06:19.002 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) Unhandled websocket event: 32 05-14 15:06:19.002 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) Unhandled websocket event: 29 05-14 15:06:19.022 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: ERR: SSL connect error 337047686: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) onConnectionError, state: 0 ... 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) onConnectionClosed, state: 2 ... 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: onConnectionClosed, WebSocket (0x63287538) is closing by server. 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) onConnectionClosed DONE! 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) Unhandled websocket event: 45 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) Unhandled websocket event: 33 05-14 15:06:21.482 15705-15838/com.bailing.MoneyGuest D/WebSocket.cpp: WebSocket (0x63287538) onConnectionClosed, state: 3 ... 05-14 15:06:21.502 15705-15810/com.bailing.MoneyGuest D/jswrapper: JS: [object Object] 05-14 15:06:21.502 15705-15810/com.bailing.MoneyGuest D/jswrapper: JS: DeviceData.statics.isgettrue 05-14 15:06:21.522 15705-15810/com.bailing.MoneyGuest D/jswrapper: JS: 连接失败 05-14 15:06:21.522 15705-15810/com.bailing.MoneyGuest D/jswrapper: JS: [object Object] 05-14 15:06:21.522 15705-15810/com.bailing.MoneyGuest D/jswrapper: JS: 连接关闭

4赞

你这种帖子一点有用信息都没有不会有人回复的

其次,通过报错信息,可以看出是ca 根文件校验失败。

按理说这个应该是openssl层的库校验不通过,所以我应该去openssl那里找问题,但是也没有找到处理的方式。

希望cocos creator引擎开发人员能够提供一些帮助

第一次提问,创建问题时没有添加描述

现在问题描述的挺好的,可惜我没用过SSL,提供不了帮助,希望引擎组重视你这个问题

1赞

问题已经解决了,具体过程我给大家描述清楚一点:

首先可以确定问题出在openssl 层次上,证书是不正确的。

证书申请:申请证书的的时候,申请者可以获取服务端证书(ssl)文件和秘钥(key)文件,还有一个中间证书,这是是重中之重。

服务端配置:服务端配置好服务端用的证书以及客户端用的证书之后,客户端 cocos create打包安卓程序开始连接,然后无论如何都连接不上。

第一个问题:客户端链接不上服务器,报“没有设置根证书”的错误

第一个问题解决:使用var ws = new WebSocket("wss://h5.zltianhen.com/uc", null, cc.url.raw("证书文件"));的方式跳过了该错误

第二个问题:继续打包运行,报证书验证失败的错误"certificate verify failed"。

第二个问题解决:
1. 先测试服务端的和客户端是否都运行正常,让浏览器访问一下服务器,结果正常,让安卓包打包的程序访问一下其他wss建议的服务器,结果正常。于是我得出这个错误很明显出在openssl内部校验的问题上,但是还需要验证一下。
2. 使用openssl工具来测试ca文件是否正常,openssl命令:
openssl s_client -showcerts -connect "链接地址" -servername "链接中的host(example.com)" -CAfile "ca文件"
如果该命令成功了,则说明这个ca文件是对的,失败了则说明ca文件是错的
3. 使用申请证书时第三方所给予的中间链文件,重要的事情说三遍,中间链文件,中间链文件,中间链文件来执行openssl命令,然后openssl工具将会报错,缺少根证书文件。
4. 使用浏览器去下载你的根证书文件(der编码),下载成功后,打开根证书文件,复制内容,直接粘贴到你的中间链文件的最后面中,从而获得一个新的证书文件
5. 再次使用Openssl命令,用刚合成的证书文件去测试,测试通过。
6. 使用刚合成的证书文件打包安卓app,wss链接成功。

8赞

中间链文件是哪个?怎么拿到?2、3、4、5步有没有详细的教程?

你申请证书的时候,如果给了你中间链证书,那你就有,如果没有给你,那你就没有

我觉得楼主说的很清楚的啊

我也遇到了这个问题,wss在iOS/Windows/微信/Web(chrome)平台都能链接成功,唯独在android上报证书验证错误certificate verify failed,然而证书用openssl命令验证确是通过的:

  1. 使用openssl工具来测试ca文件是否正常,openssl命令:
    openssl s_client -showcerts -connect “链接地址” -servername “链接中的host(example.com)” -CAfile “ca文件”

调试了服务器代码,的确是在握手时客户端证书验证不通过,至于为啥不通过,没闹明白。

后来想想,现在访问https网站时,都是单向验证,客户端都不用自带证书的,就换了一种思路解决:
cocos的websocket原生平台在iOS平台是用iOS提供的OC库,其他平台用的都是libwebsockets开源库,而且版本略老,是2.1.0版(2016年发的)。
我就把android平台的websocket实现改成了java的开源库:Java-WebSocket,通过jni调用实现了WebSocketImpl,之后Android平台就能正常使用wss了,也不用带什么证书。

根据网站xxx.pem获取安卓websocket所需的根证书的方法

  1. 第一步,打开window操作系统 (mac下面不知道怎么导出证书)
  2. 第二部, 将网站证书xxxx.pem更名为xxx.cer
  3. 第三部, 双击xxx.cer
    * 选择[证书路径]选项卡
    * 鼠标点击下方证书树的根节点
    * 鼠标点击下方查看证书按钮
    * 点击[证书详情]选项卡
    * 点击[导出证书]
    * 选择 base64模式
    导出的文件就是 安卓Websocket第三个参数所需的文件
7赞

您好,我遇到这个问题,卡了好长时间,想请教您下具体的实现,不知道能否加一下好友,感激不尽

我用楼上的方法导出根证书试了是可行的,不用改引擎底层,至于为什么不想深究了,按理客户端是不用带证书的。我建议还是不要动引擎底层吧,不然以后升级引擎很麻烦,你就按楼上的方法用导出的根证书而不是用服务器的证书。

根据网站xxx.pem获取安卓websocket所需的根证书的方法

  1. 第一步,打开window操作系统 (mac下面不知道怎么导出证书)
  2. 第二部, 将网站证书xxxx.pem更名为xxx.cer
  3. 第三部, 双击xxx.cer
    * 选择[证书路径]选项卡
    * 鼠标点击下方证书树的根节点
    * 鼠标点击下方查看证书按钮
    * 点击[证书详情]选项卡
    * 点击[导出证书]
    * 选择 base64模式
    导出的文件就是 安卓Websocket第三个参数所需的文件

另外如果是win7系统,导出证书按钮就是在证书详细信息页签有个“复制到文件”按钮

3赞

导出这个这个文件后仍然无效啊,郁闷中,可否提供点帮助

1赞

如果证书路径问题,可以参考 http://forum.cocos.com/t/websocket/67895/2?u=544811043

貌似使用cocos官方测试案列里的ca证书也是可以的

1赞

请问楼主,websocket你们能够在原生android与iOS上连通不

你好,cocos creator的websocket没有第三个设置证书的参数呢。

这个方法好使

同样使用这个方案解决。

1赞