HarmonyOS鸿蒙Next中如何实现webview拦截所有网页中的请求,然后再原生应用端实现加解密?

HarmonyOS鸿蒙Next中如何实现webview拦截所有网页中的请求,然后再原生应用端实现加解密? 现在有一个需求,需要嵌入一个已有的现成网页,网页已经完成不能修改。

现在要拦截这个网页中所有请求,有些需要加密,有些不需要,在原生APP侧要进行对应的处理,该怎么做?请给我一个简单的demo,比如请求一个天气信息,显示出来,然后拦截了修改一下。里面还会遇到跨域的问题,搞了好久没搞出来……

最好不要直接贴文档,一个简单demo就行

9 回复

楼主可以尝试使用setWebSchemeHandler来做处理:

为当前Web组件设置WebSchemeHandler, WebSchemeHandler类用于拦截指定scheme的请求。

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  schemeHandler: webview.WebSchemeHandler = new webview.WebSchemeHandler();

  build() {
    Column() {
      Button('setWebSchemeHandler')
        .onClick(() => {
          try {
            this.controller.setWebSchemeHandler('http', this.schemeHandler);
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
          }
        })
      Web({ src: 'www.example.com', controller: this.controller })
    }
  }
}

参考文档:Class (WebviewController)-@ohos.web.webview (Webview)-ArkTS API-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者

更多关于HarmonyOS鸿蒙Next中如何实现webview拦截所有网页中的请求,然后再原生应用端实现加解密?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


Webview请求拦截及加解密处理示例:

// 使用ArkWeb最新Kits导入方式

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  // 存储自定义响应头
  private headers: webview.Header[] = [
    { headerKey: "Access-Control-Allow-Origin", headerValue: "\*" },
    { headerKey: "Content-Type", headerValue: "application/json" }
  ];

  build() {
    Column() {
      // 创建Webview组件
      Web({ src: "https://your-page-url.com", controller: this.controller })
        .onInterceptRequest((event) => {
          // 拦截所有请求
          const interceptedUrl = event.request.getRequestUrl();
          
          // 判断需要加密的请求类型
          if (interceptedUrl.includes('/weather')) {
            // 构造加密响应
            const encryptedData = this.encryptData({
              temperature: "25℃",
              weather: "Sunny"
            });
            
            // 返回自定义响应
            return {
              response: {
                data: encryptedData,
                headers: this.headers,
                statusCode: 200
              }
            };
          } else {
            // 其他请求直接放行
            return { response: null };
          }
        })
    }
  }

  // 示例加密方法
  private encryptData(data: object): string {
    // 实际加解密逻辑需要根据业务实现
    return JSON.stringify(data);
  }
}

找HarmonyOS工作还需要会Flutter技术的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

  • Web组件加载URL时可以使用onLoadIntercept在加载URL之前触发回调,用于判断是否阻止此次的访问。
  • onInterceptRequest也可以用于拦截URL并返回响应数据,onLoadIntercept返回true则直接拦截URL请求,onLoadIntercept返回false则走onInterceptReques的回调。
  • onOverrideUrlLoading也可以进行拦截,在iframe加载HTTP(S)协议或about:blank时不会触发该回调,加载非HTTP(S)协议的跳转可以触发,调用loadUrl(String)主动触发的跳转不会触发该回调。

用schemeHandler或者onInterceptRequest拦截,如果加载的是本地的HTML页面,跨域

// 设置允许可以跨域访问的路径列表
this.controller.setPathAllowingUniversalAccess([
  getContext().resourceDir,
  getContext().filesDir + "/example",
])
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct PageWebIntercept {
  // 创建Web控制器
  controller: webview.WebviewController = new webview.WebviewController();
  schemeHandler: webview.WebSchemeHandler = new webview.WebSchemeHandler();

  build() {
    Column() {
      Web({
        controller: this.controller,
        src: 'https://developer.huawei.com/consumer/cn/doc/games-guides/games-quickgame-manifest-0000002351944509#section829569145720' // 需加载的网页地址
      })
        .javaScriptAccess(true)
        .fileAccess(true)
        .domStorageAccess(true)
        .onlineImageAccess(true)
        .onControllerAttached(() => {
          console.info("onControllerAttached");
          try{
            this.schemeHandler.onRequestStart((request: webview.WebSchemeHandlerRequest,
              resourceHandler: webview.WebResourceHandler) => {
              console.info('schemeHandler:' + request.getRequestUrl());
              if (request.getRequestUrl().endsWith("xxx")) {
                // 获取请求头
                let url = request.getRequestUrl();

                // 获取请求头
                let header = request.getHeader();

                // 获取请求方法
                let method = request.getRequestMethod();

                // 获取请求体
                let stream = request.getHttpBodyStream();

                // 构造响应体返回
                let response = new webview.WebSchemeHandlerResponse();

                return true
              }
              return false
            })

            this.controller.setWebSchemeHandler('https', this.schemeHandler);

          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
          }
        })
        .onInterceptRequest((event) => {
          if (event) {
            console.info('url:' + event.request.getRequestUrl());
            // 拦截页面请求
            if (event.request.getRequestUrl() == 'xxx') {
            }
          }
          return null;
        })
    }
  }
}

没满足要求,这个只能拦截地址栏的,不能拦截所有api请求的,

我需要拦截这个网页的请求,在原生应用端实现无感加解密,也就是说网页不需要改,想原生APP拿到请求之后操作,请问这个可以做吗?

在HarmonyOS Next中,使用WebviewController的onInterceptRequest方法拦截网页请求。通过注册拦截回调,获取请求URL及参数,传递至原生层进行加解密处理。处理完成后,使用WebviewController的proceed方法继续加载修改后的请求或响应数据。

在HarmonyOS Next中,可以通过WebviewController的onInterceptRequest方法拦截所有网页请求,并在原生端处理加解密逻辑。以下是简单示例:

import webview from '@ohos.web.webview';

// 创建WebviewController实例
let webviewController: webview.WebviewController = webview.WebviewController.create();

// 设置请求拦截回调
webviewController.onInterceptRequest((request) => {
  // 根据URL判断是否需要加密处理
  if (request.url.includes('weather-api.com')) {
    // 原生端加密逻辑(示例)
    const encryptedData = nativeEncrypt(request.url);
    
    // 返回自定义响应
    return {
      responseData: encryptedData,
      responseMimeType: 'application/json',
      responseEncoding: 'utf-8'
    };
  }
  
  // 不需要处理的请求返回null
  return null;
});

// 原生加密方法(需自行实现)
function nativeEncrypt(url: string): string {
  // 这里实现你的加密逻辑,例如:
  // 1. 发起原生网络请求
  // 2. 对响应数据进行加密
  // 3. 返回加密后的数据
  return JSON.stringify({ encrypted: true, data: 'your_encrypted_data' });
}

// 加载网页
webviewController.loadUrl('https://your-webpage.com');

注意:

  1. 跨域问题需要在服务器端配置CORS,客户端无法直接绕过
  2. 加密逻辑需要根据具体需求在nativeEncrypt方法中实现
  3. 对于不需要拦截的请求返回null即可继续正常加载

这个示例展示了基本的请求拦截和响应修改流程,实际使用时需要根据具体加密需求完善nativeEncrypt方法的实现。

回到顶部