MST

星途 面试题库

面试题:Flutter中如何配置HTTPS网络请求

在Flutter项目里,描述一下配置HTTPS网络请求的步骤,包括可能需要添加的依赖、证书处理等相关操作。
40.0万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

1. 添加依赖

pubspec.yaml 文件中添加 httpdio 依赖,以发起网络请求。例如,添加 http 依赖:

dependencies:
  http: ^0.13.4

如果选择 dio,添加如下依赖:

dependencies:
  dio: ^4.0.6

然后运行 flutter pub get 下载依赖。

2. 证书处理

安卓平台

  1. 信任系统证书:默认情况下,Flutter 安卓应用会信任系统证书,因此如果请求的服务器使用的是受信任的 CA 颁发的证书,无需额外配置证书。
  2. 使用自定义证书
    • 将证书文件(例如 your_cert.crt)放到 android/app/src/main/res/raw 目录下(如果没有 raw 目录,需手动创建)。
    • android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java 文件中添加如下代码:
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.PluginRegistry;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import io.flutter.plugins.http.HttpPlugin;

public class GeneratedPluginRegistrant {
  public static void registerWith(PluginRegistry registry) {
    if (alreadyRegisteredWith(registry)) {
      return;
    }

    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();

    try {
      CertificateFactory cf = CertificateFactory.getInstance("X.509");
      InputStream caInput = registry.context().getResources().openRawResource(R.raw.your_cert);
      Certificate ca;
      try {
        ca = cf.generateCertificate(caInput);
      } finally {
        caInput.close();
      }

      String keyStoreType = KeyStore.getDefaultType();
      KeyStore keyStore = KeyStore.getInstance(keyStoreType);
      keyStore.load(null, null);
      keyStore.setCertificateEntry("ca", ca);

      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
      tmf.init(keyStore);

      SSLContext sslContext = SSLContext.getInstance("TLS");
      sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
      httpClientBuilder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0]);
      httpClientBuilder.hostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
          return true;
        }
      });
    } catch (CertificateException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (KeyStoreException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (KeyManagementException e) {
      e.printStackTrace();
    }

    HttpPlugin.registerWith(registry.registrarFor("io.flutter.plugins.http.HttpPlugin"), httpClientBuilder.build());
  }

  private static boolean alreadyRegisteredWith(PluginRegistry registry) {
    final String key = GeneratedPluginRegistrant.class.getCanonicalName();
    if (registry.hasPlugin(key)) {
      return true;
    }
    registry.registrarFor(key);
    return false;
  }
}

iOS平台

  1. 信任系统证书:与安卓类似,默认情况下,Flutter iOS 应用会信任系统证书。
  2. 使用自定义证书
    • 将证书文件(例如 your_cert.cer)添加到 ios/Runner 项目中,并确保其 Target Membership 勾选了 Runner
    • ios/Runner/Info.plist 文件中添加如下配置:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>your_domain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
            <key>NSIdentityConstraints</key>
            <dict>
                <key>NSCertificateTransparencyPublicKeyHashes</key>
                <array>
                    <string>YOUR_CERTIFICATE_HASH</string>
                </array>
            </dict>
        </dict>
    </dict>
</dict>

要获取证书哈希,可以使用以下命令(在 macOS 上):

openssl x509 -noout -in your_cert.cer -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

3. 发起HTTPS请求

使用 http

import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  final response = await http.get(Uri.parse('https://your_domain.com/api/data'));
  if (response.statusCode == 200) {
    print(response.body);
  } else {
    print('Request failed with status: ${response.statusCode}.');
  }
}

使用 dio

import 'package:dio/dio.dart';

Future<void> fetchData() async {
  Dio dio = Dio();
  try {
    Response response = await dio.get('https://your_domain.com/api/data');
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}