Как заставить приложение IOS доверять localhost для разработки API - PullRequest
0 голосов
/ 12 июня 2019

Используя Visual Studio для Mac, я создал RESFUL API (разработанный из шаблона проекта API), который из коробки выводит очень простой файл JSON (т. Е. ["Value1", "value2"]) при следующемurl: https://localhost:5001/api/values.

Итак, пока я запускаю API в Visual Studio в фоновом режиме, я также запускаю XCode на том же компьютере;в этом я разрабатываю приложение, которое должно подключиться к URL-адресу API и вывести ожидаемый ответ JSON.

Проблема в том, что он постоянно завершается ошибкой из-за ошибки доверия: «Ошибка доверия SSL TIC ... Ошибка загрузки HTTP NSURLSession / NSURLConnection».

Из того, что я исследовал, я считаю, что мне нужно установить самоподписанный сертификат localhost на мой эмулятор XCode, чтобы приложение могло доверять URL-адресу.Как мне получить доступ к этому локальному сертификату?

Или это даже правильный путь?

Код, который генерирует ошибку доверия:

// Specify the base url...
static NSString *const API_URL = @"https://localhost:5001";
// Specify completed url ...
NSString *urlAppend = [NSString stringWithFormat:@"/api/values"];
NSString *urlStr = [[[NSString alloc] initWithString:API_URL]
stringByAppendingString:urlAppend];        

// Specify the URL object that can return JSON, XML, etc....
NSURL *url = [[NSURL alloc] initWithString:urlStr];

// Create an NSURLSessionDataTask that does the GET request at the specified URL (using NSURLSession shared session)...
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
              dataTaskWithURL:url
              completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

                  // Handle response (output respnose to log window))...
                  NSLog(@"%@", [output initWithData:data  encoding:(NSASCIIStringEncoding)] ? : @"no data");
              }];

// Start task ....
[task resume];

Ответы [ 2 ]

0 голосов
/ 28 июня 2019

Лучший способ сделать это - Выполнить ручную проверку подлинности доверия сервера для URL-адреса сервера разработки localhost (работает в фоновом режиме).Это делается с помощью URLSession: didReceiveChallenge: completeHandler: метод делегирования вашего NSURLSessionDelegate ;что даст вам возможность сопоставить URL-адрес локального хоста и вручную доверять ему, когда начинается задача данных сеанса (до того, как она будет отклонена из-за ненадежного самозаверяющего сертификата).

Вот как:

Шаг 1: Обернуть операции NSURLSession в классе, скажем «Networking», который реализует протокол NSURLSessionDelegate;и добавьте метод делегата, который вручную доверяет вашему локальному URL-адресу (указанному как 'DEV_URL').

// Networking.h
#import <Foundation/Foundation.h>

@interface Networking : NSObject <NSURLSessionDelegate>
- (void) fetchContentsOfUrl:(NSURL *)url
                 completion:(void (^)(NSData *data, NSError *error)) completionHandler;
@end
// Networking.m
#import "Networking.h"

static NSString *const DEV_URL = @"https://localhost:5001";
@implementation Networking
- (void) fetchContentsOfUrl:(NSURL *)url
                 completion:(void (^)(NSData * _Nullable, NSError * _Nullable))completionHandler {
    NSURLSession *dataSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

    NSURLSessionDataTask *dataTask = [dataSession
                                      dataTaskWithURL:url
                                      completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                                          if (completionHandler == nil) {
                                              return;
                                          }

                                          if (error){
                                              completionHandler(nil, error);
                                              return;
                                          }

                                          completionHandler(data, nil);
                                      }];

    [dataTask resume];
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSURL* baseURL = [NSURL URLWithString:DEV_URL];
        if ([challenge.protectionSpace.host isEqualToString:baseURL.host]) {
            NSLog(@"trusting connection to host %@", challenge.protectionSpace.host);
            completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
        } else {
            NSLog(@"Not trusting connection to host %@", challenge.protectionSpace.host);
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        }
    }
    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
@end

Шаг 2. Замените исходный код на создание экземпляра класса Networking и вызов функцииfetchContentsOfUrl: завершение: метод, который вызывает NSURLSessionDataTask, следующим образом:

    Networking *networker = [[Networking alloc] init];
    [networker fetchContentsOfUrl:url completion:^(NSData *data, NSError *error) {        
        if (error == nil) {
            NSString *output = [NSString alloc];
            NSLog(@"%@", [output initWithData:data  encoding:(NSASCIIStringEncoding)] ? : @"no data");
        }
    }];

Все готово !!

0 голосов
/ 13 июня 2019

Вы можете попробовать это: в верхней части каждого из ваших контроллеров ViewController, которые делают любые HTTP-запросы, прямо под разделом импорта, добавьте этот код:

@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end

Затем вниз туда, где вы делаете запроспозвоните по этому номеру:

[request setHTTPBody:data];

[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];

NSError *error;
NSHTTPURLResponse  *response = nil;

NSData *data2 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...