Finding and auto-filling HTML login forms in a UIWebView using JavaScript

前端 未结 4 1337
自闭症患者
自闭症患者 2020-12-24 09:30

i have a UIWebView which acts like an internet browser and loads the HTML of the webpages that it is at.

in the webViewController, the method webViewDidFinishLoad, w

相关标签:
4条回答
  • 2020-12-24 09:55

    I had some problems with finding the fields, so I adapted the code to target the fields more specific:

       - (void)webViewDidFinishLoad:(UIWebView*)theWebView
        {
    
        NSString *savedUsername = @"username";
        NSString *savedPassword = @"pass";
    
          if (savedUsername.length != 0 && savedPassword.length != 0) {
    
              NSString *loadUsernameJS = [NSString stringWithFormat:@"var inputFields = document.getElementsByTagName('input'); \
                                    for (var i = inputFields.length >>> 0; i--;) { if(inputFields[i].name == 'username') inputFields[i].value = '%@';}", savedUsername];
    
              NSString *loadPasswordJS = [NSString stringWithFormat:@" \
                                    for (var i = inputFields.length >>> 0; i--;) { if(inputFields[i].name == 'password') inputFields[i].value = '%@';}", savedPassword];
    
        //autofill the form
           [theWebView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
           [theWebView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
          }
    
    
        return [super webViewDidFinishLoad:theWebView];
      }      
    
    0 讨论(0)
  • 2020-12-24 09:56

    I don't think finding a reference to the input elements will be difficult using javascript, but it's amending them that is not straightforward with the UIWebView.

    A hacky way to achieve what you want in the way you describe could be done by getting the HTML from the UIWebView, amending it, then loading it back in. E.g.:

    // Get the HTML from the UIWebView
    NSMutableString *html = [[[self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML;"] mutableCopy] autorelease];
    
    // Find the range of the first input element.
    NSRange firstInputRange = [html rangeOfString:@"<input" options:NSCaseInsensitiveSearch];
    // Check if it was found...
    if (firstInputRange.location != NSNotFound) {
        // Add replace with the populated value attribute appended.
        [html replaceCharactersInRange:firstInputRange withString:@"<input value='username'"];
    
        // Now do the same for the second input range, checking the html after the first input.
        NSRange secondInputRange = [html rangeOfString:@"<input" options:NSCaseInsensitiveSearch range:NSMakeRange(firstInputRange.location+firstInputRange.length, html.length - firstInputRange.location - firstInputRange.length)];
        // And if found, append the populated value attribute.
        if (secondInputRange.location != NSNotFound) {
            [html replaceCharactersInRange:secondInputRange withString:@"<input value='password'"];
        }
    
    }
    
    // Finally, load the amended HTML back into the UIWebView/
    [self.webView loadHTMLString:html baseURL:nil];
    
    0 讨论(0)
  • 2020-12-24 10:01

    OK, so there's no one-size-fits-all for this. You can get pretty close, but it will never work on every website, since a website could possibly have multiple login forms, or multiple fields that make up the username (some banks have that).

    But this will get you in the right direction. To get all the password fields (mostly just one), use this:

    document.querySelectorAll("input[type='password']")
    

    To get all the text input fields, use this:

    document.querySelectorAll("input[type='text']")
    

    For the text input fields, you'll most likely get multiple results (maybe search fields and stuff). So you'll have to iterate over them and look for common IDs or names, like "username", "user", "user_name", "UID" and so on.

    This is how you could use it in Objective-C:

    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        NSString *savedUsername = @"peter";
        NSString *savedPassword = @"Pan123";
    
        if (savedUsername.length != 0 && savedPassword.length != 0) { 
            //create js strings
            NSString *loadUsernameJS = [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
            for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", savedUsername];
            NSString *loadPasswordJS = [NSString stringWithFormat:@"document.querySelectorAll(\"input[type='password']\").value ='%@'", savedPassword];
    
            //autofill the form
            [self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
            [self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
        }
    }
    

    Please note: It fills every textfield with the username and only the first password field with the password.

    Enjoy.

    0 讨论(0)
  • 2020-12-24 10:03

    Based on a previous answer I created this 3 methods.

    This method will fill the username/email fields it should work on a lot of cases :

    - (void)completeUserFieldsForWebView:(UIWebView *)webView withUsername:(NSString *)username {
    
        NSString *loadUsernameJS =
        [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='email']\"); \
         for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", username];
        NSString *loadText =
        [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
         for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", username];
        [webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
        [webView stringByEvaluatingJavaScriptFromString: loadText];
    
    }
    

    This one will fill the password fields:

    - (void)completePasswordFieldsForWebView:(UIWebView *)webView withPassword:(NSString *)password {
    
        NSString *loadPasswordJS =
        [NSString stringWithFormat:@"var passFields = document.querySelectorAll(\"input[type='password']\"); \
         for (var i = passFields.length>>> 0; i--;) { passFields[i].value ='%@';}", password];
        [webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
    
    }
    

    And to perfom the sign-in :

    - (void)clickOnSubmitButtonForWebView:(UIWebView *)webView {
    
        NSString *performSubmitJS = @"var passFields = document.querySelectorAll(\"input[type='submit']\"); \
        passFields[0].click()";
        [webView stringByEvaluatingJavaScriptFromString:performSubmitJS];
    
    } 
    
    0 讨论(0)
提交回复
热议问题