【iOS安全】JS 调用Objective-C中WKWebview Handler的三种方式

有三种实现途径

1. WKScriptMessageHandler

OC部分:注册并实现Handler

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

c 复制代码
// 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"

javascript 复制代码
// Invoke in JavaScript code
window.webkit.messageHandlers.nativeMethod.postMessage();

2. WebViewJavascriptBridge

OC部分:注册并实现Handler

注册名为"nativeMethod"的Handler

c 复制代码
// 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

js 复制代码
WebViewJavascriptBridge.callHandler('nativeMethod', data, function(responseData) {
    // 处理来自Objective-C的响应数据
    console.log(response); 
});

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

c 复制代码
{
    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端就可以这么调用:

c 复制代码
WebViewJavascriptBridge.callHandler('getLocation', function(response) {
  console.log(response); 
});

确实能调用起来

3. DSBridge

这个不是很常见

OC部分:

c 复制代码
@implementation JsObject
- (NSString *) nativeMethod:(NSString *) msg
{
    ...
}
@end

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

JS部分:

js 复制代码
var dsBridge=require("dsbridge");
var str=dsBridge.call("nativeMethod","arg");

参考:

Medusa Attack: Exploring Security Hazards of {In-App}{QR} Code ScanningC//32nd USENIX Security Symposium (USENIX Security 23). 2023: 4607-4624.

相关推荐
WIN赢16 小时前
【抽象思想-从复杂中抽离简单、收敛的口子】
java·前端·javascript
冰暮流星18 小时前
javascript之webstorage用法
开发语言·javascript·ecmascript
执子念的飞鱼18 小时前
浏览器直接预览 Pages、Numbers、Keynote:iWork 格式真正难在哪
前端·javascript
用户3452081538819 小时前
我给 DSH 写了读 10x 数据的插件
javascript
执子念的飞鱼19 小时前
70MB Excel 浏览器预览失败:定位 XLSX 重复解压与内存峰值
javascript·性能优化
12.=0.19 小时前
【REVIEW_C】【持续更新】
服务器·前端·javascript
Brown.alexis19 小时前
es6知识点4-自备使用
前端·javascript·es6
Hilaku20 小时前
为什么同一段代码在 Safari 上永远有 Bug?
前端·javascript·程序员
张元清20 小时前
React scrollIntoView + useRef:滚动到指定元素 (2026)
javascript·react.js