You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:15:29