首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >flutter应用程序中拒绝flutter_inappwebview本地https连接

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

Stack Overflow用户
提问于 2020-11-28 00:18:56
回答 1查看 1.1K关注 0票数 0

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

由于flutter_inappwebview中提供的本地应用程序服务器不处理ssl连接,因此我使用以下代码将InAppLocalHostServer类替换为InAppLocalHostSecureServer:

代码语言:javascript
运行
复制
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的客户端代码:

代码语言:javascript
运行
复制
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);
        },
      ),
    );
  }
}

控制台中未显示错误,但颤振页面显示以下错误消息:

net::ERR_CONNECTION_REFUSED

欢迎任何帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-04 20:38:11

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

我的问题很简单,就是在服务器启动完成之前,我过早地构建了InAppWebView。解决方案很简单,只需在服务器启动时将一个标志设置为true,并仅在标志为true时创建InAppWebView。

除此之外,WebRTC在本地主机上没有https,我在Android和iOS上测试了它。所以在这个用例中不需要本地https。

但不管怎样,如果因为任何其他原因,有人需要提供https本地内容,这篇文章中的代码可以作为基础。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65040548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档