无法使用 Flutter 连接到 wss

Posted

技术标签:

【中文标题】无法使用 Flutter 连接到 wss【英文标题】:Cannot connect to wss with Flutter 【发布时间】:2020-01-03 15:12:38 【问题描述】:

我在 Nodejs 中编写了一个 wss 服务器,现在我正在尝试使用 Flutter 连接到这样的服务器。

这是 NodeJS 中的代码:

//Dependencies
const WebSocket = require('ws');
const fs = require('fs');
const https = require('https');
//Dependencies

//Server declarations
const server = https.createServer(
    key: fs.readFileSync('pathTo/key.pem'),
    cert: fs.readFileSync('pathTo/cert.pem')
);
server.listen(xxxx);
const wss = new WebSocket.Server( server );
//Server declarations

wss.on('connection', function connection(ws)

  ws.on('message', function incoming(message)
  
      console.log('Received: ' + message);
      ws.send('echo: ' + message);
   );
   ws.send('Connected!');
);

这是 Flutter 中的代码:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:web_socket_channel/io.dart';
import 'package:connectivity/connectivity.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

class MyApp extends StatelessWidget

  @override
  Widget build(BuildContext context)
  
    final title = 'LumenApp Prototype';
    IOWebSocketChannel channel;
    try
    
      channel = new IOWebSocketChannel.connect('wss://xxxxxxxx.xxx.xxx:xxxx/');
      MyHomePageState.noResponse = false;
    
    catch(e)
    
      MyHomePageState.noResponse = true;
    
    return MaterialApp(
      title: title,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        primaryTextTheme: TextTheme(
          title: TextStyle(
            color: Colors.yellow[600],
          ),
        ),
      ),
      home: MyHomePage(
        title: title,
        channel: channel,
      ),
    );
  

Flutter 上的错误是:WebSocketChannelException: WebSocketChannelException: HandshakeException: Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:354))

这发生在这个函数内部:

  void initPlatformState()
  
    widget.channel.stream.listen((message)
    
      setState(()  noResponse = false; );
      //Handle message...
    ,
    onError: (error)
    
      print(error);
      if(mounted)
      
        setState(() noResponse = true;);
      
    ,
    onDone: ()
    
      if(mounted)
      
        setState(() noResponse = true; );
      
    );
  

我使用了一个由 openssl 制作的自签名证书服务器端。 知道如何解决这个问题吗?

【问题讨论】:

第一个假设是您的 websocket 服务器没有 SSL 证书,因此无法运行 WSS。 @JoãoSoares 我使用 OpenSSL 获得了一个 ssl 密钥和一个 ssl 证书。 您是否测试过您的 WSS 在不是您的 Flutter 应用的其他客户端上正常工作? @JoãoSoares 我尝试使用 Postman,但无论是使用 ws 还是使用 wss,它都不起作用,即使使用 ws 和 Flutter 也可以。 那里肯定发生了一些奇怪的事情,但您需要确保您的服务器正常工作,然后再继续查看您的 Flutter 应用程序是否存在问题。 【参考方案1】:

如果你碰巧碰到this GitHub post,你可以按照this comment的临时修复:

class MyHttpOverrides extends HttpOverrides
  @override
  HttpClient createHttpClient(SecurityContext context)
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  


void main()
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());

它适用于具有自签名证书的本地 IP。

详细说明,here is the same solution:

只是为了清楚起见,特别是为了新手 Flutter/Dart,这是启用此功能所需要做的 项目中的全局选项:

    在您的 main.dart 文件中,添加或导入以下类:
HttpClient createHttpClient(SecurityContext? context)
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;     ```
    在您的主函数中,在函数定义后添加以下行:

HttpOverrides.global = MyHttpOverrides();

This 评论对解决这个问题很有帮助,请 请注意...

这应该在开发模式下使用,不要这样做 你想发布到生产中,这个答案的目的是让 开发对您来说更容易一些,对于生产,您需要修复 您的证书问题并正确使用它,请查看其他答案 因为它可能对您的情况有所帮助。

另外值得一提的是,签名证书现在免费提供 (https://letsencrypt.org/)。

另外,我认为 Flutter 团队正在努力向enhance the documentation 寻求有关此问题的更好参考。正在跟踪here。

【讨论】:

以上是关于无法使用 Flutter 连接到 wss的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 MQTT 连接到 wss?

无法连接到 wss [更新]

无法连接到 wss://(连接建立错误:net::ERR_CONNECTION_CLOSED)

无法从 https 客户端通过 wss 连接到 emqx mqtt 代理

无法连接到本地 Node.js 安全 WebSocketServer

Flutter 无法连接到 Firebase Firestore 数据库