简体   繁体   English

使用JavaScript在UIWebView中查找和自动填充HTML登录表单

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

i have a UIWebView which acts like an internet browser and loads the HTML of the webpages that it is at. 我有一个UIWebView,它像一个互联网浏览器,并加载它所在的网页的HTML。

in the webViewController, the method webViewDidFinishLoad, would have loaded the HTML from the webpage when the webpage finish loading on the UIWebView. 在webViewController中,方法webViewDidFinishLoad,当网页在UIWebView上完成加载时,会从网页加载HTML。

From the HTML i would like to sieve out textfields to facilitate the auto population of that textfield with values stored in my database. 从HTML我想筛选出文本字段,以便使用我的数据库中存储的值来促进该文本字段的自动填充。

Any methods to do that? 有什么办法吗? The method should be able to work on all websites. 该方法应该能够在所有网站上工作。

Set text for a textfield in UIWebView has almost what might help me, but i have tried it and the text field never got filled. 在UIWebView中为文本字段设置文本几乎可以帮助我,但我已经尝试过,文本字段永远不会被填充。

In a login page there will be two text fields so i tried using 在登录页面中将有两个文本字段,所以我尝试使用

document.getElementsByTagName('INPUT')[0].value
document.getElementsByTagName('INPUT')[1].value 

to input in the values but no magic. 输入值但没有魔法。

Edit: i have tried other position in the array. 编辑:我已尝试在阵列中的其他位置。 the username and password for Facebook is [3] and[4] whereas for amazon it is [11] and [14]. Facebook的用户名和密码是[3]和[4],而亚马逊则是[11]和[14]。 so the position of where the fields are using the above method is kinda random. 所以字段使用上述方法的位置有点随机。 Any other suggestion that will work for all website? 任何其他适用于所有网站的建议?

Edit2: i could try Edit2:我可以试试

document.getElementsById('id_name').value

but the ID method is not going to work for me as i need a universal method that will identify textfields on any websites(all websites uses different ID names) 但ID方法不适用于我,因为我需要一种通用方法来识别任何网站上的文本字段(所有网站使用不同的ID名称)

Also it seems to me that some of the websites have consistently set this tabindex="1" for username and tabindex="2" for password. 在我看来,有些网站一直为用户名设置tabindex =“1”,密码为tabindex =“2”。

for instance in the webpage like Facebook: 例如在Facebook这样的网页中:

<input type="text" class="inputtext" name="email" id="email" value="" tabindex="1" />
<input type="password" class="inputtext" name="pass" id="pass" tabindex="2" /> 

amazon: 亚马逊:

<input id="ap_email" name="email" value="" type="email" size="30" maxlength="128" tabindex="1" autocorrect="off" autocapitalize="off" />
<input id="ap_password" name="password" type="password" maxlength="1024" size="20"  tabindex="2" onkeypress="displayCapsWarning(event,'ap_caps_warning', this);" class="password"/> 

dbs bank: dbs银行:

<input type="text" tabindex="1" maxlength="20" size="32" name="UID" id="UID">
<input type="password" onkeyup="keyUp(event)" onkeydown="return onlyNumerics(event)" tabindex="2" maxlength="9" size="32" name="PIN" id="PIN" autocomplete="off">

but i didn't see this tabindex in google: 但我没有在谷歌看到这个tabindex:

<input type="text" spellcheck="false" name="Email" id="Email" value="">
<input type="password" name="Passwd" id="Passwd">

any suggestion? 有什么建议吗?

The Ultimate goal is to be able to sieve out Username and Password Text field for all/any websites. 最终目标是能够筛选出所有/任何网站的用户名和密码文本字段。 =) =)

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. 因此,您必须迭代它们并查找常用ID或名称,例如“username”,“user”,“user_name”,“UID”等。

This is how you could use it in Objective-C: 这是你在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. 请享用。

Based on a previous answer I created this 3 methods. 基于之前的答案,我创建了这3种方法。

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];

} 

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];
  }      

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. 我不认为使用javascript找到对输入元素的引用会很困难,但它修改它们对于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. Eg: 通过从UIWebView获取HTML,修改它,然后将其重新加载,可以实现以您描述的方式实现所需内容的hacky方式。例如:

// 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];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM