Xamarin: iOSでHTTPリクエストを行うと"App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file."エラー

概要

iOS 9以上ではApp Transport Securityの導入により、HTTPリクエストを実行するとエラーが発生する。その対応。

Info.plistの設定変更

<プロジェクト名>.iOS以下にあるInfo.plistを開き、以下の設定を追加する。 f:id:shindo1687:20200429220549p:plain

NSAppTransportSecurityについては以下を参照。
https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity
*iOS 10以上ではこの設定が無視される、と書いてあるがApp Transport Securityの導入が延期(https://developer.apple.com/news/?id=12212016b)された結果、現状ではiOS 13でも問題なく適用されている。

サンプルコード

"http://www.google.com"に対するGETリクエストを実行する。

static readonly HttpClient client = new HttpClient();

private static async Task HttpRequestAsync()
{
    HttpResponseMessage response = await client.GetAsync("http://www.google.com");
    response.EnsureSuccessStatusCode();
    byte[] responseBody = await response.Content.ReadAsByteArrayAsync();
    Console.WriteLine("responseBody=" + Encoding.UTF8.GetString(responseBody));
}

async void OnButtonClicked(System.Object sender, System.EventArgs eventArgs)
{
    try
    {
        await HttpRequestAsync();
    }
    catch (Exception e)
    {
        Console.WriteLine($"{e}");
    }
}

設定変更前の実行結果

App Transport SecurityによってHTTPリクエストがブロックされる。

2020-04-29 22:14:23.652 XamarinHttp.iOS[2498:840291] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
Thread started:  #4
2020-04-29 22:14:23.678 XamarinHttp.iOS[2498:840277] System.Net.Http.HttpRequestException: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection. ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection., NSErrorFailingURLStringKey=http://www.google.com/, NSErrorFailingURLKey=http://www.google.com/, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <63869A38-EDA0-4689-A5F0-2FF17C08DDB8>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <63869A38-EDA0-4689-A5F0-2FF17C08DDB8>.<1>, NSUnderlyingError=0x281297480 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}}
   --- End of inner exception stack trace ---
  at System.Net.Http.NSUrlSessionHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x001d4] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/Foundation/NSUrlSessionHandler.cs:462 
  at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) [0x0017e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:506 
  at XamarinHttp.MainPage.HttpRequestAsync () [0x0002f] in /Users/shindo/Projects/XamarinHttp/XamarinHttp/MainPage.xaml.cs:31 
  at XamarinHttp.MainPage.OnButtonClicked (System.Object sender, System.EventArgs eventArgs) [0x0002e] in /Users/shindo/Projects/XamarinHttp/XamarinHttp/MainPage.xaml.cs:54 

設定変更後の実行結果

問題なくHTTPリクエストが実行できる。

2020-04-29 21:54:06.596 XamarinHttp.iOS[2493:836960] responseBody=<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
        
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>