flutter_inappwebview本地https连接在flutter应用程序中被拒绝

Posted

技术标签:

【中文标题】flutter_inappwebview本地https连接在flutter应用程序中被拒绝【英文标题】:flutter_inappwebview local https connection refused in flutter app 【发布时间】:2021-03-10 10:13:23 【问题描述】:

我正在尝试通过 https 从资产中提供本地内容,以便访问需要 ssl 的 webrtc 等功能。

由于flutter_inappwebview中提供的本地应用服务器 不处理 ssl 连接,我用 InAppLocalHostSecureServer 替换了 InAppLocalHostServer 类,代码如下:

import 'dart:io';
import 'dart:async';

import 'package:flutter/services.dart' show rootBundle;
import 'package:mime/mime.dart';

class InAppLocalHostSecureServer 
  HttpServer _server;
  int _port = 8443;

  InAppLocalHostSecureServer(int port = 8443) 
    this._port = port;
  

  ///Starts a server on http://localhost:[port]/.
  ///
  ///**NOTE for ios**: For the iOS Platform, you need to add the `NSAllowsLocalNetworking` key with `true` in the `Info.plist` file (See [ATS Configuration Basics](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35)):
  ///```xml
  ///<key>NSAppTransportSecurity</key>
  ///<dict>
  ///    <key>NSAllowsLocalNetworking</key>
  ///    <true/>
  ///</dict>
  ///```
  ///The `NSAllowsLocalNetworking` key is available since **iOS 10**.
  Future<void> start() async 
    if (this._server != null) 
      throw Exception('Server already started on https://localhost:$_port');
    

    var completer = Completer();

    runZoned(() async 
      SecurityContext context = new SecurityContext();
      var chain = await rootBundle.load('assets/certificates/cert.pem');
      var key = await rootBundle.load('assets/certificates/key.pem');
      context.useCertificateChainBytes(chain.buffer.asInt8List());
      context.usePrivateKeyBytes(key.buffer.asInt8List(), password: 'dartdart');

      HttpServer.bindSecure('127.0.0.1', _port, context).then((server) 
        print('Server running on https://localhost:' + _port.toString());

        this._server = server;

        server.listen((HttpRequest request) async 
          print(request);
          var body = List<int>();
          var path = request.requestedUri.path;
          path = (path.startsWith('/')) ? path.substring(1) : path;
          path += (path.endsWith('/')) ? 'index.html' : '';

          try 
            body = (await rootBundle.load(path)).buffer.asUint8List();
           catch (e) 
            print(e.toString());
            request.response.close();
            return;
          

          var contentType = ['text', 'html'];
          if (!request.requestedUri.path.endsWith('/') &&
              request.requestedUri.pathSegments.isNotEmpty) 
            var mimeType =
                lookupMimeType(request.requestedUri.path, headerBytes: body);
            if (mimeType != null) 
              contentType = mimeType.split('/');
            
          

          request.response.headers.contentType =
              ContentType(contentType[0], contentType[1], charset: 'utf-8');
          request.response.add(body);
          request.response.close();
        );

        completer.complete();
      );
    , onError: (e, stackTrace) 
      print('Error: $e $stackTrace');
    );

    return completer.future;
  

  ///Closes the server.
  Future<void> close() async 
    if (this._server != null) 
      await this._server.close(force: true);
      print('Server running on http://localhost:$_port closed');
      this._server = null;
    
  

大部分代码是原始类的复制粘贴。

我改变的是我调用 HttpServer.bindSecure 而不是 HttpServer.bind 并提供 openssl 证书和密钥。

服务器似乎在控制台中没有错误记录的情况下启动,但我无法访问它。

这是尝试访问本地 url 的客户端代码:


import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'InAppLocalHostSecureServer.dart';

class WebAudioTest extends StatefulWidget 
  @override
  _WebAudioTestState createState() => _WebAudioTestState();


class _WebAudioTestState extends State<WebAudioTest> 
  InAppWebViewController webView;
  InAppLocalHostSecureServer localhostServer;
  String url = "https://127.0.0.1:8443/assets/web/index.html";

  @override
  void initState() 
    super.initState();
    this.init();
  

  void init() async 
    this.localhostServer = new InAppLocalHostSecureServer();
    await localhostServer.start();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: const Text('Web Audio Test'),
      ),
      body: InAppWebView(
        initialUrl: url,
        initialHeaders: ,
        initialOptions: InAppWebViewGroupOptions(
            crossPlatform: InAppWebViewOptions(
          debuggingEnabled: true,
        )),
        onWebViewCreated: (InAppWebViewController c) 
          webView = c;
        ,
        onConsoleMessage: (controller, consoleMessage) 
          print("CONSOLE MESSAGE: " + consoleMessage.message);
        ,
      ),
    );
  

控制台没有报错,但是flutter页面显示如下报错信息:

net::ERR_CONNECTION_REFUSED

欢迎任何帮助。

【问题讨论】:

在这种情况下我不确定,但请尝试将 127.0.0.1 更改为 10.0.2.2。原因:***.com/questions/55908089/… 嗨,阿米特,感谢您的提示。不幸的是,我不确定它是否适用于这个问题。在我当前的问题中,本地 Web 服务器位于手机上的颤振应用程序本身中。它仅适用于 http,但不适用于 https。仅使用 http,我尝试了 localhost 和 127.0.0.1 并且都作为 IP 地址工作。在 https 中没有,但我不确定是因为地址或证书还是导致问题的任何原因。不幸的是,控制台中没有日志,所以我现在被卡住了。 【参考方案1】:

好的,回答我自己的问题:

我遇到的问题只是我在服务器完成启动之前过早地构建了 InAppWebView。解决方法很简单,只需要在服务器启动的时候设置一个flag为true,在flag为true的时候才创建InAppWebView。

除此之外,WebRTC 在 localhost 上无需 https 即可工作,我在 android 和 iOS 上对其进行了测试。所以这个用例不需要本地 https。

但无论如何,如果出于任何其他原因需要提供 https 本地内容,本文中的代码可以作为此的基础。

【讨论】:

以上是关于flutter_inappwebview本地https连接在flutter应用程序中被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.IllegalStateException:尝试创建未注册类型的平台视图:com.pichillilorenzo/flutter_inappwebview

无法在 Flutter Web 视图中使用本地存储

从 RStudio 发布到本地 Shiny Server

从本地 LAMP 访问 SoapClient 和 file_get_contents

批量删除git 本地分支远程分支tag

批量删除git 本地分支远程分支tag