Zoh*_*Ali 10 javascript android recaptcha webview android-webview
我在WebView中添加了一个JavaScript函数(Kotlin):
val webView = findViewById(R.id.webview) as WebView
webView.getSettings().setJavaScriptEnabled(true)
webView.addJavascriptInterface(this, "android")
webView.getSettings().setBuiltInZoomControls(false)
webView.loadUrl(url)
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
webView.loadUrl("javascript:(function captchaResponse (token){" +
" android.reCaptchaCallbackInAndroid(token);" +
" })()")
}
}
Run Code Online (Sandbox Code Playgroud)
该函数工作正常,但问题是它在WebView中添加它时会立即运行.我只想将它作为JavaScript函数包含在内,只有当用户填写reCAPTCHA时才能从HTML调用它.我怎样才能做到这一点?
为了reCaptchaCallbackInAndroid从JavaScript 运行您的公开方法,当用户提交成功的 reCAPTCHA响应时,首先要确保通过标记属性实际监听 reCAPTCHA :callbackg-recaptcha
<div class="g-recaptcha"
data-sitekey="{{your site key}}"
data-callback="myCustomJavaScriptCallback"
></div>
Run Code Online (Sandbox Code Playgroud)
grecaptcha.render(
'g-recaptcha-element-id', {
sitekey: '{{your site key}}',
callback: 'myCustomJavaScriptCallback'
}
)
Run Code Online (Sandbox Code Playgroud)
然后,当页面完成了在加载WebView,添加您的JavaScript回调函数的window对象使用webView.loadUrl:
webView.loadUrl("""
javascript:(function() {
window.myCustomJavaScriptCallback = function(token) {
android.reCaptchaCallbackInAndroid(token);
/* also add your additional JavaScript functions
and additional code in this function */
}
})()
""".trimIndent())
Run Code Online (Sandbox Code Playgroud)
最后,当用户提交成功的reCAPTCHA响应时,您myCustomJavaScriptCallback将通过reCAPTCHA调用您的公开reCaptchaCallbackInAndroid方法token.
由于你使用的是Kotlin,在这种情况下,你可以简单地使用多行字符串文字.
由于您正在向JavaScript公开方法,因此请务必了解安全问题.
如果您将来需要额外的JavaScript注入(更多方法曝光,DOM操作等),请查看此文章.
设置reCAPTCHA以captchaResponse通过tag attribute以下方式调用JavaScript函数:
<div class="g-recaptcha"
...
data-callback="captchaResponse"
...
></div>
Run Code Online (Sandbox Code Playgroud)
或通过其API:
grecaptcha.render(
'...', {
...
callback: 'captchaResponse'
...
}
)
Run Code Online (Sandbox Code Playgroud)
并将您的captchaResponse回调函数添加到window:
webView.loadUrl("""
javascript:(function() {
window.captchaResponse = function(token) {
android.reCaptchaCallbackInAndroid(token);
/* also you can add further JavaScript functions
and additional code in this function */
}
})()
""".trimIndent())
Run Code Online (Sandbox Code Playgroud)
这是一个简单的,Empty Activity在Android Studio中有一个基本的LinearLayout (一个EditText和一个Button布局内)和MainActivity.kt:
package com.richardszkcs.injectjsintowebview
import android.net.Uri
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.webkit.JavascriptInterface
import kotlinx.android.synthetic.main.activity_main.*
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendButton.setOnClickListener { loadWebpage() }
}
@Throws(UnsupportedOperationException::class)
fun buildUri(authority: String) : Uri {
val builder = Uri.Builder()
builder.scheme("https")
.authority(authority)
return builder.build()
}
@JavascriptInterface
fun reCaptchaCallbackInAndroid(token: String) {
val tok = token.substring(0, token.length / 2) + "..."
Toast.makeText(this.applicationContext, tok, Toast.LENGTH_LONG).show()
}
fun loadWebpage() {
webView.getSettings().setJavaScriptEnabled(true)
webView.addJavascriptInterface(this, "android")
webView.getSettings().setBuiltInZoomControls(false)
webView.loadUrl("https://richardszkcs.github.io/recaptcha-test/")
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
webView.loadUrl("""
javascript:(function() {
window.onCaptchaSuccess = function(token) {
android.reCaptchaCallbackInAndroid(token);
}
})()
""".trimIndent())
}
}
}
}Run Code Online (Sandbox Code Playgroud)
然后使用简单的reCAPTCHA测试网站,在window.onCaptchaSuccess成功提交reCAPTCHA时调用该函数,并Toast使用Android模拟器部分显示reCAPTCHA令牌:
完全披露:我做了reCAPTCHA测试网站准备/测试/调试类似的情况.
尝试像这样注入脚本,
function addCode(code){
var addedScript= document.createElement('script');
addedScript.text= code;
document.body.appendChild(addedScript);}
Run Code Online (Sandbox Code Playgroud)
现在调用该函数,例如
val codeToExec = "function captchaResponse (token){" +
"android.reCaptchaCallbackInAndroid(token);" +
"}";
Run Code Online (Sandbox Code Playgroud)
现在执行 loadurl 像,
webview.loadUrl("javascript:(function addCode(code){
var addedScript= document.createElement('script');
addedScript.text= code;
document.body.appendChild(addedScript);})(codeToExec));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2507 次 |
| 最近记录: |