【iOS安全】JS 调用Objective-C中WebView Handler的三种方式 | WKWebView | UIWebView

有三种实现途径

1. WKScriptMessageHandler

主要用在WKWebView中,实测下来是目前最常用的

OC部分:注册并实现Handler
将OC中的方法"nativeMethod"注册为JavaScript Message Handler,从而WebView中的JavaScript代码可以调用该方法

// Register in Objective-C code
- (void)setupWKWebView
{
    // [WKWebViewConfiguration alloc]返回一个被分配和初始化的WKWebViewConfiguration对象的指针
    // init方法是WKWebViewConfiguration类的实例方法
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    
    configuration.userContentController = [[WKUserContentController alloc] init];
    
    // 将OC中的方法"nativeMethod"注册为JavaScript Message Handler,从而可以在WebView中执行JavaScript代码时调用该方法
    [configuration.userContentController 
        addScriptMessageHandler:self // addScriptMessageHandler是方法名,self是参数1
        name:@"nativeMethod"]; // name是参数2
    
    // 初始化WKWebView
    WKWebView *webView = 
        [[WKWebView alloc]
            initWithFrame:self.view.frame
            configuration:configuration];
}

// Handler method defined in WKScriptMessageHandler
- (void)userContentController:
    (WKUserContentController *)userContentController //userContentController是参数1
    didReceiveScriptMessage:(WKScriptMessage *)message //message是参数2
{
    if ([message.name isEqualToString:@"nativeMethod"]) // 当JS端调用的是nativeMethod时
    {
        ... //OC端的handler逻辑实现
    }
}

JS部分:调用Handler
调用"nativeMethod"

// Invoke in JavaScript code
window.webkit.messageHandlers.nativeMethod.postMessage();

2. WebViewJavascriptBridge

主要用在UIWebView中,是旧版本的WebView
使用方法:https://github.com/marcuswestin/WebViewJavascriptBridge

OC部分:注册并实现Handler
注册名为"nativeMethod"的Handler

// OC中 调用bridgeForWebView:方法,来初始化WebViewJavascriptBridge
// self.bridge将被设置为WKWebView的navigationDelegate属性
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];

[self.bridge registerHandler:@"nativeMethod" //参数1,JS端以这个函数名调用该注册的native方法
    handler: //参数2的参数名,冒号后面跟着参数2的参数值,是一个block;当JS端调用nativeMethod方法时,OC端执行该block
    ^(id data, WVJBResponseCallback responseCallback) 
    // ^代表后面是一个block 
    // data是JS端传递过来的数据
    // responseCallback是 OC端的 block 执行完毕之后,往 JS 端传递的数据
    {
        ... // block中的代码,这些代码在JS端调用nativeMethod时被执行
    }
];

JS部分:调用Handler

// 轮子代码,直接粘贴
function setupWebViewJavascriptBridge(callback) {
	if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
	if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
	window.WVJBCallbacks = [callback];
	var WVJBIframe = document.createElement('iframe');
	WVJBIframe.style.display = 'none';
	WVJBIframe.src = 'https://__bridge_loaded__';
	document.documentElement.appendChild(WVJBIframe);
	setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}

// 调用setupWebViewJavascriptBridge
setupWebViewJavascriptBridge(function(bridge) {
	//JS调用OC: bridge.callHandler
	bridge.callHandler('nativeMethod', data, function(responseData) {
		// 处理来自Objective-C的响应数据
		console.log("JS received response:", responseData)
	})
	
	//OC调用JS: registerHandler
	// 参见 https://github.com/marcuswestin/WebViewJavascriptBridge
})

例如我们使用Frida分析出来,某app的webview中有如下handler:

{
    callNavigationSelectView = "<__NSMallocBlock__: 0x281d4a440>";
    checkNotificationPermission = "<__NSMallocBlock__: 0x281d4b240>";
    clickControlToShare = "<__NSMallocBlock__: 0x281d4bf00>";
    couponPaySuccess = "<__NSMallocBlock__: 0x281d4a780>";
    doQRScan = "<__NSMallocBlock__: 0x281d4bf80>";
    faceDetect = "<__NSMallocBlock__: 0x281d4bcc0>";
    getDeviceAlipay = "<__NSMallocBlock__: 0x281d4a4c0>";
    getDeviceId = "<__NSMallocBlock__: 0x281d4a800>";
    getDeviceInfo = "<__NSMallocBlock__: 0x281d4a680>";
    getLocation = "<__NSMallocBlock__: 0x281d4a600>";
    getNetworkStatus = "<__NSMallocBlock__: 0x281d4b0c0>";
    getOtherDeviceInfo = "<__NSMallocBlock__: 0x281d4b540>";
    getSMDeviceId = "<__NSMallocBlock__: 0x281d4a2c0>";
    getTripEmail = "<__NSMallocBlock__: 0x281db04c0>";
    getUserInfo = "<__NSMallocBlock__: 0x281d4a540>";
    goToKF = "<__NSMallocBlock__: 0x281d4a340>";
    goToVideoPlayer = "<__NSMallocBlock__: 0x281d4a700>";
    hideLoadingDialog = "<__NSMallocBlock__: 0x281d4b3c0>";
    jdPayHandle = "<__NSMallocBlock__: 0x281d4b900>";
    jumpToMiniPro = "<__NSMallocBlock__: 0x281d4a380>";
    requestNotificationPermission = "<__NSMallocBlock__: 0x281d4af00>";
    saveImage = "<__NSMallocBlock__: 0x281d4a500>";
    sendMsg = "<__NSMallocBlock__: 0x281d4a5c0>";
    shareOnTheWebviewPage = "<__NSMallocBlock__: 0x281d4a640>";
    shareWxImages = "<__NSMallocBlock__: 0x281d4b4c0>";
    shareWxMinipg = "<__NSMallocBlock__: 0x281d4a580>";
    startAuthoritySetting = "<__NSMallocBlock__: 0x281d4a300>";
    startNetworkSetting = "<__NSMallocBlock__: 0x281d4a7c0>";
    statusBarShare = "<__NSMallocBlock__: 0x281d4ad40>";
    uploadTripEmail = "<__NSMallocBlock__: 0x281d49b40>";
    webviewClose = "<__NSMallocBlock__: 0x281d4a740>";
    webviewGoBack = "<__NSMallocBlock__: 0x281d4a480>";
}

这时候在JS端就可以这么调用:

WebViewJavascriptBridge.callHandler('getLocation', function(response) {
  console.log(response); 
});

确实能调用起来
在这里插入图片描述

3. DSBridge

这个不是很常见

OC部分:

@implementation JsObject
- (NSString *) nativeMethod:(NSString *) msg
{
    ...
}
@end

DWKWebView* dwebview = [[DWKWebView alloc] initWithFrame:bounds];
[dwebview addJavascriptObject:[[JsObject alloc] init] namespace:nil];

JS部分:

var dsBridge=require("dsbridge");
var str=dsBridge.call("nativeMethod","arg");

参考:
Medusa Attack: Exploring Security Hazards of {In-App}{QR} Code Scanning[C]//32nd USENIX Security Symposium (USENIX Security 23). 2023: 4607-4624.

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Objective-C ,系统自带的选择弹窗是通过使用 UIAlertController 来实现的。以下是实现步骤: 1.导入头文件: ```objective-c #import <UIKit/UIKit.h> ``` 2.创建 UIAlertController 对象并设置标题、消息和样式: ```objective-c UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"选择性别" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; ``` 3.创建 UIAlertAction 对象,并添加到 UIAlertController : ```objective-c UIAlertAction *maleAction = [UIAlertAction actionWithTitle:@"男" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 处理选择男性的逻辑 }]; UIAlertAction *femaleAction = [UIAlertAction actionWithTitle:@"女" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 处理选择女性的逻辑 }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:maleAction]; [alertController addAction:femaleAction]; [alertController addAction:cancelAction]; ``` 4.在需要弹出选择弹窗的地方,使用 presentViewController 方法显示 UIAlertController: ```objective-c UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; [rootViewController presentViewController:alertController animated:YES completion:nil]; ``` 这样就可以实现一个简单的选择性别的系统自带弹窗了。你可以根据自己的需要调整样式和逻辑处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值