5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter ✕ gRPC ✕ オレオレ証明書

Last updated at Posted at 2020-05-14

2020/5/17 更新
どうやらiOS13以降だと↓の通りの記述を入れても HandshakeException が発生するようです。
https://support.apple.com/ja-jp/HT210176
公式でのアナウンスもあり、クライアントの努力で解決するのは実質不可能と思われます。
正規の証明書発行することをオススメします。

はじめに

gRPCをFlutter(Dart)で使うときにオレオレ証明書で死ぬほど躓いたのでメモ。
オレオレ証明書のための HogeClient の設定までにつまづいたこと、そしてどう修正していったのかを順を追って説明していきます。

目次

1. pbgrpc.dartがない
2. SocketException
3. HandshakeException
4. 黙ってクラッシュ
5. 動いた

#1. pbgrpc.dartがない
生成の設定ミスです。設定については割愛します。

#2. SocketException

実際のコード

_createClient() {
    final channel = ClientChannel('https://hoge.com');
    return HogeClient();
}

エラー

Unhandled Exception: gRPC Error (14, Error connecting: SocketException: Failed host lookup: 'https://hoge.com' (OS Error: nodename nor servname provided, or not known, errno = 8))

原因

https:// は不要でした。

#3. HandshakeException

実際のコード

_createClient() {
    final channel = ClientChannel('hoge.com');
    return HogeClient();
}

エラー

Unhandled Exception: gRPC Error (14, Error connecting: HandshakeException: Handshake error in client (OS Error: 
	CERTIFICATE_VERIFY_FAILED: ok(handshake.cc:354)))

原因

信頼できない証明書(オレオレ証明書)を使っていることによるエラーです。

#4. 黙ってクラッシュ

実際のコード

_createClient() {
    final channel = ClientChannel(
        'hoge.com', 
        options: ChannelOptions(
          credentials: ChannelCredentials.insecure(),
        ),
    );
    return HogeClient();
}

エラー

Androidのみで出力されるエラー

Unhandled Exception: gRPC Error (2, HTTP/2 error: Connection error: Connection is being forcefully terminated. (errorCode: 10))

flutter run -vのクラッシュ直前抜粋

[   +5 ms] DevFS: Deleting filesystem on the device
(file:///Users/{ユーザ名とかデバイスIDとか}/)
[ +260 ms] Ignored error while cleaning up DevFS: TimeoutException after 0:00:00.250000: Future not completed

原因

ChannelCredentials.insecure(), は認証をオフにするパラメータです。オレオレ証明書でも認証は必要なためクラッシュします。

#5. 動いた

実際のコード

_createClient() async {
    final trustedRoot = await rootBundle.load('assets/key/api.pem');
    final channelCredentials = ChannelCredentials.secure(
      certificates: trustedRoot.buffer.asUint8List(),
    );
    final channel = ClientChannel(
      'hoge.com',
      options: channelOptions,
    );
    client = ClipServiceClient(channel);
}

ポイント

  • 動かすためにオレオレ証明書の .pem が必要なため発行しましょう。
  • assets内にそれを保存し 実際のコード を参考にクライアントを生成しましょう。

感想

4. でずっと黙ってクラッシュしてたので丸一日潰れました。
この記事によって誰かの丸一日が潰れることを阻止できれば本望。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?