# ArkWeb本地资源跨域问题和解决方案

#### 问题现象

为了提高安全性，ArkWeb内核不允许file协议或者resource协议访问URL上下文中来自跨域的请求，在使用ArkWeb加载H5页面时，会因为该限制遇到跨域相关的问题，本文总结了本地资源跨域问题和解决方案。

#### 背景知识

*   setPathAllowingUniversalAccess：设置一个路径列表，当file协议访问该路径列表中的资源时，允许跨域访问本地文件，也允许跨域访问其他在线资源；
*   onInterceptRequest：当Web组件加载URL之前触发该回调，用于拦截URL并返回响应数据；
*   WebSchemeHandler：用于拦截指定scheme请求的拦截器。

#### 问题定位

*   问题一：加载本地静态资源报跨域错误，控制台常见报错：
    
    ```
    "Uncaught SecurityError: Failed to construct 'Worker': Script at 'xxx' cannot be accessed from origin 'null'."
    ```
    
*   问题二：本地资源请求服务端跨域，控制台常见报错：
    
    ```
    Access to XMLHttpRequest at 'xxx' from origin 'resource://rawfile' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb-extension, https, chrome-untrusted, arkweb, data, chrome-extension, chrome.
    ```
    

#### 分析结论

针对本地资源跨域问题，通常有以下两种解决方案：

方案一：通过setPathAllowingUniversalAccess设置一个路径列表，再使用file协议访问该路径列表中的资源，允许跨域访问本地文件；

方案二：对本地资源进行拦截和替换：采用http或https等协议，替代原先使用的file或resource协议进行加载。

#### 修改建议

*   针对问题一加载本地资源跨域的问题，解决方案如下：
    
    方案一：通过setPathAllowingUniversalAccess()设置一个路径列表，当file协议访问该路径列表中的资源时，允许跨域访问本地文件。
    
    设置路径列表时，有以下注意点：
    
    1.  如果设置跨域的路径为resourceDir，对应静态资源目录为应用resources目录下的resfile目录（与rawfile目录同级）；
        
    2.  如果设置跨域路径为应用文件目录的子目录，不能直接指定应用沙箱目录，需要指定应用沙箱目录的子目录。例如不能直接指定沙箱文件目录/data/storage/el2/base/haps/entry/files，需要指定文件目录下的子目录，如：/data/storage/el2/base/haps/entry/files/example。
    
    方案二：参考本地资源跨域问题解决方法的方法一，使用http或https协议替代file或resource协议，即先加载自定义构造的http或者https的URL，再结合Web的设置请求拦截器接口如onInterceptRequest()拦截替换加载资源。
    
*   针对问题二遇到的本地资源请求服务端跨域，解决方案如下：
    
    方案一：因setPathAllowingUniversalAccess接口也允许跨域访问其他在线资源，可直接使用该接口解决；
    
    方案二：使用http或https协议替代file或resource协议的方案，需要注意的是，加载自定义构造的URL需要与服务端URL一致；
    
    方案三：可参考远程请求跨域中的代理请求方案，通过设置拦截器如setWebSchemeHandler()拦截H5中的http请求，并通过RCP作为跨域请求的代理请求，请求完成后将结果和响应头设置到resourceHandler中通知Web组件被拦截的请求已经完成，实现代码demo可参考：基于ArkWeb拦截器和Cookies管理能力实现Web页面跨域。