英文:
Cannot connect to wss with Flutter
问题
我写了一个在Node.js中的wss服务器,现在我正在尝试使用Flutter连接到这个服务器。
以下是Node.js中的代码:
//依赖项
const WebSocket = require('ws');
const fs = require('fs');
const https = require('https');
//依赖项
//服务器声明
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 });
//服务器声明
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; });
//处理消息...
},
onError: (error)
{
print(error);
if(mounted)
{
setState((){ noResponse = true;});
}
},
onDone: ()
{
if(mounted)
{
setState((){ noResponse = true; });
}
});
}
我在服务器端使用了自签名证书,使用了openssl制作。有什么办法解决这个问题吗?
英文:
I wrote a wss server in Nodejs and now I'm trying to connect to such server using Flutter.
Here's the code in NodeJS:<br>
//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!');
});
Here's the code in Flutter:<br>
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,
),
);
}
}
The error on Flutter is: WebSocketChannelException: WebSocketChannelException: HandshakeException: Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:354))
This happens inside this function:
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; });
}
});
}
I used a self-signed certificate server-side made with openssl.<br>
Any idea how to solve this?
答案1
得分: 1
如果您偶然遇到了这个GitHub帖子,您可以按照此评论中的临时解决方法进行操作:
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。
为了详细说明,这里是相同的解决方案:
仅为了清晰起见,特别是对于Flutter/Dart的新手,以下是在项目中全局启用此选项所需执行的操作:
- 在您的main.dart文件中,添加或导入以下类:
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
}
}
- 在您的main函数中,在函数定义之后添加以下行:
HttpOverrides.global = MyHttpOverrides();
这个评论对通过这个问题非常有帮助,请注意...
这应该在开发模式下使用,请在要发布到生产时不要这样做,这个答案的目的是使开发对您来说更容易一些,对于生产,您需要修复您的证书问题并正确使用它,请查看其他答案,因为它可能对您的情况有所帮助。
值得一提的是,现在可以免费获得签名证书(https://letsencrypt.org/)。
此外,我认为Flutter团队正在努力完善文档,以更好地参考此问题。它正在这里跟踪。
英文:
If you happen to bumped in this GitHub post, you can follow the temporary fix from 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());
> }
It works on local ip with self signed certificate.
To elaborate, here is the same solution:
> Just for the sake of clarity specially for the newcomers to
> Flutter/Dart, here is what you need to do in order to enable this
> option globally in your project:
>
> 1. In your main.dart file, add or import the following class:
>
> > class MyHttpOverrides extends HttpOverrides{ @override
> > HttpClient createHttpClient(SecurityContext? context){
> > return super.createHttpClient(context)
> > ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true; } }
>
> 2. In your main function, add the following line after function definition:
>
>
>
> > HttpOverrides.global = MyHttpOverrides();
>
>
> This
> comment was very helpful to pass through this matter, and please
> note that...
>
>
> > This should be used while in development mode, do NOT do this when
> > you want to release to production, the aim of this answer is to make
> > the development a bit easier for you, for production, you need to fix
> > your certificate issue and use it properly, look at the other answers
> > for this as it might be helpful for your case.
Another thing worth mentioning, signed certificates are available for free now (https://letsencrypt.org/).
Also, I think the Flutter team is working to enhance the documentation for better reference regarding this issue. It is being tracked here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论