1

I'm using a custom NSURLProtocol in order to be able to save the username and password from a form that is loaded in a webView and automatically log the user in. My issue is that I can get the data, but I can't complete the action to login the user as the webpage uses some JS to listen to the response and complete the form action. Is there a way to do it?

Here's my current CustomURLProtocol class:

class CustomURLProtocol: NSURLProtocol {

    var connection: NSURLConnection!

    override class func canInitWithRequest(request: NSURLRequest) -> Bool {
        if NSURLProtocol.propertyForKey("customProtocolKey", inRequest: request) != nil {
            return false
        }
        return true
    }

    override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
        return request
    }

    override func startLoading() {
        let newRequest = request.mutableCopy() as! NSMutableURLRequest
        NSURLProtocol.setProperty(true, forKey: "customProtocolKey", inRequest: newRequest)

        // Look for user credentials
        if request.URL?.description == "https://www.website.com/Account/Login" {
            if let data = request.HTTPBody {
                let dataString: String = NSString(data: data, encoding: NSASCIIStringEncoding) as! String
                // Code for reading user credentials goes here
            }
        }

        connection = NSURLConnection(request: newRequest, delegate: self)
    }

    override func stopLoading() {
        if connection != nil {
            connection.cancel()
        }
        connection = nil
    }

    func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
        client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
    }

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
        client!.URLProtocol(self, didLoadData: data)
    }

    func connectionDidFinishLoading(connection: NSURLConnection!) {
        client!.URLProtocolDidFinishLoading(self)
    }

    func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
        client!.URLProtocol(self, didFailWithError: error)
    }
}

Is there something I'm missing or is wrong in my logic?

Thanks in advance

Tchelow
  • 593
  • 4
  • 15

1 Answers1

0

So if I understand correctly, you're intercepting the call just to preserve the credentials so you can log the user in automatically later? If you only care about the login request you could move the url check to canInitWithRequest, but that's a side issue.

Using a custom NSURLProtocol correctly shouldn't affect the response, so the web page should behave normally. I notice that you're using NSURLConnection, which is deprecated, so you might want to look at using NSURLSession but again that's a side issue.

Have you stepped through the code to see where it's failing? Are your connection delegate methods being called? Is "webViewDidFinishLoad" being called on the web view?

Or are you not talking about the initial form submission, but subsequent ones when you're trying to log in the user with the stored credentials?

Leedrick
  • 41
  • 5
  • First of all, I have also to support iOS 7, so that's why I'm using 'deprecated' methods. Second, the request is made through AJAX and, for that reason, it does not go through my delegate. That's why I'm trying to use a custom `NSURLProtocol`. Does that help? – Tchelow Apr 21 '16 at 06:08
  • NSURLSession was released in ios7. – Leedrick Apr 22 '16 at 01:21
  • Anyway, it does help a bit, but it's not clear to me which part is failing. are you saying that when you intercept the request, the response isn't returned? Or that the response is invalid so the web page doesn't react? If the former, can you see it hitting the right NSURLProtocol methods? If the latter, can you validate the response is correct? – Leedrick Apr 22 '16 at 01:30