Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofill Username and Password in UIWebView

I'm doing a very easy app for me. When I launch this app, it simply bring me to this web page https://social.tre.it/expert.

I would like to automatise login so is there a way to autofill username and password, check the "I accept condition" mark and push "login" button?

I tried this Autofill Username and Password UIWebView Swift but it doesn't work, I'm not the creator of the page so I don't know exactly how it's structured.

Would be cool even if iCloud keychains would fill the forms...but maybe I'm asking too much!

like image 888
Matte.Car Avatar asked Feb 01 '16 20:02

Matte.Car


1 Answers

You can use JavaScript to do it.

If you inspect the page, you can pretty easily spot the IDs of the text input fields (expert_email and expert_password) and execute some JS code to fill them.

Implement the webViewDidFinishLoad method of the UIWebView delegate like so:

OBJECTIVE-C:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    //fill data
    NSString *email = @"[email protected]";
    NSString *password = @"mypassword";
    NSString *fillDataJsCall = [NSString stringWithFormat:@"document.getElementById('expert_email').value = '%@';document.getElementById('expert_password').value = '%@';", email, password];
    [webView stringByEvaluatingJavaScriptFromString:fillDataJsCall];

    //check checkboxes
    [webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('expert_remember_me').checked = true; document.getElementById('expert_terms_of_service').checked = true;"];

    //submit form
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void)
    {
       [webView stringByEvaluatingJavaScriptFromString:@"document.forms[\"new_expert\"].submit();"];
    });
}

SWIFT:

func webViewDidFinishLoad(webView: UIWebView) {

    // fill data
    let savedUsername = "USERNAME"
    let savedPassword = "PASSWORD"

    let fillForm = String(format: "document.getElementById('expert_email').value = '\(savedUsername)';document.getElementById('expert_password').value = '\(savedPassword)';")
    webView.stringByEvaluatingJavaScriptFromString(fillForm)

    //check checkboxes
    webView.stringByEvaluatingJavaScriptFromString("document.getElementById('expert_remember_me').checked = true; document.getElementById('expert_terms_of_service').checked = true;")

     //submit form
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * NSEC_PER_SEC)), dispatch_get_main_queue()){
        webView.stringByEvaluatingJavaScriptFromString("document.forms[\"new_expert\"].submit();")
    }
}

This should fill your info. However, this code can easily break if this website changes its structure in the future. This method of executing JS code is more reasonable when you're handling your own pages.

Edit:

I updated the code to demonstrate how to check the checkboxes and how to submit the form.

Some notes:

  • when the login fails the page is reloaded, so you're going to end up with an endless loop of calls to webViewDidFinishLoad since you're trying to submit over and over again, so you might want to add some logic to break in this case. That's why I put a delay before submitting in order to be able to see what's going on.
  • In addition to the info in the previous point - you're going to get calls to webViewDidFinishLoad anyway after login is successful (when redirected to the next page) so you might want to raise a flag once a different page loads (perform the login attempt only when on the login page).
like image 144
Artal Avatar answered Sep 20 '22 23:09

Artal