React Native应用Tapjacking防护咨询:setFilterTouchesWhenObscured无效
React Native Tapjacking 防护方案
一、Android 端现有实现优化
你之前的setFilterTouchesWhenObscured设置可能因为未覆盖全量视图或缺少配套标记,导致安全扫描未通过。可以通过以下方式强化防护:
- 添加FLAG_SECURE标记:该标记会阻止窗口内容被截屏/录屏,同时辅助拦截Tapjacking攻击,在
MainActivity的onCreate中补充:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 开启窗口安全标记 getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); // 保留原有触摸过滤逻辑,双重保障 View myView = findViewById(android.R.id.content); myView.setFilterTouchesWhenObscured(true); }
- 监听窗口遮挡状态(API 30+):
FLAG_WINDOW_IS_PARTIALLY_OBSCURED是系统状态标记,需通过监听回调处理遮挡事件,在MainActivity中添加:
@Override public void onAttachedToWindow() { super.onAttachedToWindow(); getWindow().getDecorView().setOnWindowFocusChangeListener((v, hasFocus) -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { boolean isObscured = v.isWindowObscured() || v.isWindowPartiallyObscured(); if (isObscured) { // 窗口被遮挡时,禁用所有触摸交互 v.setFilterTouchesWhenObscured(true); // 可选:添加全屏遮罩层彻底阻断触摸 } else { v.setFilterTouchesWhenObscured(false); } } }); }
二、React Native 端防护方案
通过封装原生模块监听系统遮挡状态,在RN层动态禁用交互:
1. 封装Android原生模块
创建TapjackingModule类,将遮挡状态通过事件发送给RN:
public class TapjackingModule extends ReactContextBaseJavaModule implements LifecycleEventListener { private ReactApplicationContext reactContext; public TapjackingModule(ReactApplicationContext context) { super(context); reactContext = context; context.addLifecycleEventListener(this); } @Override public String getName() { return "TapjackingModule"; } @Override public void onHostResume() { View decorView = reactContext.getCurrentActivity().getWindow().getDecorView(); decorView.setOnWindowFocusChangeListener((v, hasFocus) -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { boolean isObscured = v.isWindowObscured() || v.isWindowPartiallyObscured(); sendEvent("onWindowObscured", isObscured); } }); } private void sendEvent(String eventName, boolean isObscured) { reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, isObscured); } @Override public void onHostPause() {} @Override public void onHostDestroy() {} }
在MainApplication中注册该模块。
2. RN端监听并处理
在根组件中监听遮挡事件,添加全屏遮罩阻断交互:
import { useEffect, useState } from 'react'; import { View, Text, StyleSheet, NativeEventEmitter, NativeModules } from 'react-native'; const { TapjackingModule } = NativeModules; const App = () => { const [isWindowObscured, setIsWindowObscured] = useState(false); useEffect(() => { const eventEmitter = new NativeEventEmitter(TapjackingModule); const subscription = eventEmitter.addListener( 'onWindowObscured', (isObscured) => setIsWindowObscured(isObscured) ); return () => subscription.remove(); }, []); return ( <View style={styles.container}> {/* 你的应用核心内容 */} <Text>应用主界面</Text> {/* 遮挡时显示的拦截遮罩 */} {isWindowObscured && ( <View style={styles.obscureOverlay}> <Text style={styles.overlayText}>检测到窗口被遮挡,请关闭悬浮窗口后操作</Text> </View> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, obscureOverlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.7)', justifyContent: 'center', alignItems: 'center', zIndex: 9999, }, overlayText: { color: '#fff', fontSize: 16, textAlign: 'center', paddingHorizontal: 20, }, }); export default App;
三、iOS端补充防护
若需兼容iOS,可通过以下方式实现:
- 在
AppDelegate.m中开启安全窗口并监听遮挡通知:
#import <UIKit/UIKit.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 阻止截屏录屏 application.isSecure = YES; // 监听窗口被遮挡事件 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onWindowObscured:) name:UIWindowSceneDidBecomeObscuredNotification object:nil]; return YES; } - (void)onWindowObscured:(NSNotification *)notification { UIWindowScene *scene = (UIWindowScene *)notification.object; // 添加遮罩层阻断交互 UIView *overlay = [[UIView alloc] initWithFrame:scene.keyWindow.bounds]; overlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; [scene.keyWindow addSubview:overlay]; } @end
内容的提问来源于stack exchange,提问作者Vanessa
相关产品推荐
相关产品推荐

