2017-02-08 4 views
4

Ich möchte einen Proxy zu allen Netzwerkanrufen hinzufügen, die von meiner App kommen. So etwas wieiOS den gesamten Netzwerkverkehr von meiner App abfangen?

func intercept(request: URLRequest) { 
    if isOk(request) { 
    return // the request continues as normally 
    } else if isIntercepted(request) { 
    let res = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/2", headerFields: ["Content-Type": "application/json"]) 
    res.value = "{\"ok\":true}" // not that exactly work, but you get the idea 
    request.end(res) 
    } else { 
    let res = HTTPURLResponse(url: url, statusCode: 401, httpVersion: "HTTP/2") 
    res.value = "forbidden" 
    request.end(res) 
    } 
} 

Ich möchte es auf alle Anrufe von meiner App angewendet werden. Dh von meinem Code und von allen Bibliotheken und Frameworks, die ich verwende. Ist es möglich?

Ich habe Fragen über das Lesen von Datenverkehr anderer Apps (nicht möglich) und das Festlegen von Delegaten für Anrufe, die mit meinem Code gestartet wurden, gefunden. Ich würde gerne weiter mit etwas, das 1) würde automatisch für alle Verkehr und 2) gehören Verkehr von Dritten

Antwort

1

Das ist ein Job für die URLProtocol Klasse.

Von Apple docs:

Ein NSURLProtocol Objekt behandelt das Laden von protokollspezifischen URL Daten. Die NSURLProtocol-Klasse selbst ist eine abstrakte Klasse, die die Infrastruktur für die Verarbeitung von URLs mit einem bestimmten URL-Schema bietet. Sie erstellen Unterklassen für benutzerdefinierte Protokolle oder URL-Schemas , die von Ihrer App unterstützt werden.

Sie müssen Ihre eigene Unterklasse von URLProtocol implementieren und sie mit der App registrieren, damit sie verwendet werden kann. Danach werden alle Verbindungen, die von der App initialisiert wurden, das Protokoll verwenden, und Sie werden in der Lage sein, jede gewünschte Anfrage zu bearbeiten/zu blockieren.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
{ 
    guard URLProtocol.registerClass(MyURLProtocol.self) else 
    { 
     abort() 
    } 

    return true 
} 

Auch wenn Sie URLSession verwenden (und sollten!), Dann müssen Sie auch Ihre Klasse durch die Sitzungskonfigurationen registrieren:

func getURLSessionConfiguration() -> URLSessionConfiguration 
{ 
    let configuration = URLSessionConfiguration.default 

    configuration.protocolClasses = [ 
     MyURLProtocol.self 
    ] 

    return configuration 
} 

let session = URLSession(configuration: getURLSessionConfiguration()) 

Dann können Sie verwalten, was Sie blockieren möchten, von der startLoading() Methode Ihrer URLProtocol Unterklasse:

override func startLoading() 
{ 
    if self.isOK() 
    { 
     let error = NSError(domain: "GuardURLProtocol", code: 10, userInfo: [NSLocalizedDescriptionKey: "Connection denied by guard"]) 
     self.client?.urlProtocol(self, didFailWithError: error) 
    } 
    else if let task = self.task 
    { 
     task.resume() 
    } 
} 

Es gibt mehr Methoden, die Sie zu implementieren, und Sie sho Lesen Sie die documentation from Apple.

Aber als Gizmo (und Übung für mich), I have written a generic blocker protocol, und Sie sollten es überprüfen, um zu sehen, wie es funktioniert. Im unteren Bereich der Datei GuardURLProtocol.swift befindet sich eine Beispielunterklasse (BlockFPTURLSession), in der alle FTP-Anfragen durch das Schema blockiert werden.

Wenn Sie die Klasse I oben verlinkten verwenden und versuchen, eine FTP-Verbindung zu öffnen, werden Sie die folgenden Fehler sehen:

2017-02-16 23:09:45.846 URLProtocol[83111:7456862] Error: Error Domain=GuardURLProtocol Code=10 "Connection denied by guard" UserInfo={NSLocalizedDescription=Connection denied by guard} 

Viel Spaß!

+0

Danke das ist großartig! Weißt du, wie ich eine Antwort verspotten würde? Zum Beispiel, wenn die tatsächliche Antwort ist http://www.heypasteit.com/clip/7WCWX wie überlasse ich es? Ich habe versucht, \t \t 'Client .urlProtocol? (Self, didLoad: response.data (mit: .utf8))' \t \t 'Client .urlProtocolDidFinishLoading (Selbst-)' wo 'response' ist das? Text über – Guig

+0

Ich denke, Sie müssen auch 'self.client 'nennen.urlProtocolDidFinishLoading (self) 'um der URL-Verbindung/Sitzung mitzuteilen, dass das Laden endlich beendet ist, da' didLoad ... 'mehrere Male aufgerufen werden kann, um Teile der Antwortdaten zu liefern, und ein einmaliger Aufruf bedeutet nicht, dass die Verbindung besteht erledigt. –

Verwandte Themen