使用 JavaScript 在 UIWebView 中查找和自动填充 HTML 登录表单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9715100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding and auto-filling HTML login forms in a UIWebView using JavaScript
提问by at0m87
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 sieveout 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 UIWebViewhas 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]. so the position of where the fields are using the above method is kinda random. Any other suggestion that will work for all website?
编辑:我尝试过阵列中的其他位置。Facebook 的用户名和密码是 [3] 和 [4],而亚马逊是 [11] 和 [14]。所以使用上述方法的字段位置有点随机。任何其他适用于所有网站的建议?
Edit2: i could try
编辑2:我可以试试
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:
星展银行:
<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. =)
最终目标是能够筛选出所有/任何网站的用户名和密码文本字段。=)
回答by Johannes Fahrenkrug
OK, so there's no one-size-fits-all for this. You can get pretty close, but it will never work on everywebsite, 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 或名称,例如“用户名”、“用户”、“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 everytextfield with the username and only the first password field with the password.
请注意:它使用用户名填充每个文本字段,并且仅使用密码填充第一个密码字段。
Enjoy.
享受。
回答by ant_one
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];
}
回答by Ian L
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. E.g.:
可以通过从 UIWebView 获取 HTML,修改它,然后重新加载它来以你描述的方式实现你想要的东西。例如:
// 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];
回答by Martijn Mellens
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];
}