如何阻止外部资源加载到 WKWebView?

Posted

技术标签:

【中文标题】如何阻止外部资源加载到 WKWebView?【英文标题】:How to block external resources to load on a WKWebView? 【发布时间】:2015-08-20 13:44:06 【问题描述】:

我有一个加载网页的应用程序,但会阻止下载图像、字体、javascript 等。为此,我实现了一个 NSURLProtocol 子类,它与 UIWebView 配合得很好。

但是我正在迁移到 WKWebview,并意识到我精心设计的 NSURLProtocol 类不再用于过滤掉这些资源。

有没有人了解如何实现过滤/阻止?

如果您想知道我是如何进行迁移的,我从这篇文章开始:http://floatlearning.com/2014/12/uiwebview-wkwebview-and-tying-them-together-using-swift/

【问题讨论】:

【参考方案1】:

ios 11 开始你可以使用WKContentRuleList

首先,创建内容规则或列表。每个规则都由触发器和操作组成。看 Apple's Documentation on Content Rule creation

这是一个创建示例,阻止所有图像和样式表内容,但允许那些以 jpeg 结尾的内容,忽略前面的规则:

     let blockRules = """
         [
             "trigger": 
                 "url-filter": ".*",
                 "resource-type": ["image"]
             ,
             "action": 
                 "type": "block"
             
         ,
         
             "trigger": 
                 "url-filter": ".*",
                 "resource-type": ["style-sheet"]
             ,
             "action": 
                 "type": "block"
             
         ,
         
             "trigger": 
                 "url-filter": ".*.jpeg"
             ,
             "action": 
                 "type": "ignore-previous-rules"
             
         ]
      """        

拥有您的规则列表,您可以将它们添加到 ContentRuleListStore

    import WebKit
    @IBOutlet weak var wkWebView: WKWebView!

    let request = URLRequest(url: URL(string: "https://yourSite.com/")!)

    WKContentRuleListStore.default().compileContentRuleList(
        forIdentifier: "ContentBlockingRules",
        encodedContentRuleList: blockRules)  (contentRuleList, error) in

            if let error = error 
                return
            

            let configuration = self.webView.configuration
            configuration.userContentController.add(contentRuleList!)

            self.wkWwebView.load(self.request)
    

如果以后您想删除所有规则,请致电:

    self.wkWebView.configuration.userContentController.removeAllContentRuleLists()
    self.wkWebView.load(self.request)

这里是2017 WWDC video

祝你好运!

我创建了一个示例项目on Github WKContentRuleExample

【讨论】:

您对适用于 iOS 暂时没有,抱歉。在 iOS 11 之前找不到任何 API 如何使用 iOS 10 阻止外部资源加载到 WKWebView 上? 据我所知,iOS 11 之前没有阻塞资源【参考方案2】:

从 iOS 9.0 开始,无法拦截WKWebView 的网络请求。您可以通过 JavaScript 以有限的方式做到这一点。

请提交 WebKit 错误或 Apple 错误以请求此功能。我们中的许多人都需要这些钩子。

【讨论】:

我会说这不是 WebKit 错误。 android 已经具备执行此操作的功能已经有一段时间了。阻止图像加载(和许多其他事情)从一开始就存在。 Apple 根本没有公开这些功能。 提交错误是让苹果知道这是我们可以访问的功能的最佳方式。 @StefanArentz 关于如何在 iOS @NicholasAllio 只是一个想法:也许您可以在网页开始加载资源之前将内容安全策略元标记注入网页。在 WKUserScripts 的帮助下可能【参考方案3】:

如果其他人对仅离线的WKWebView 感兴趣:以下方法是对@dequin 答案的修改。它使用内容阻止规则来阻止对远程资源的所有请求(不以file:// 开头的URL):

import Cocoa
import WebKit

// Block all URLs except those starting with "file://"
let blockRules = """
[
    
        "trigger": 
            "url-filter": ".*"
        ,
        "action": 
            "type": "block"
        
    ,
    
        "trigger": 
            "url-filter": "file://.*"
        ,
        "action": 
            "type": "ignore-previous-rules"
        
    
]
"""
/// `WKWebView` which only allows the loading of local resources
class OfflineWebView: WKWebView 
    override init(frame: CGRect, configuration: WKWebViewConfiguration) 
        WKContentRuleListStore.default().compileContentRuleList(
            forIdentifier: "ContentBlockingRules",
            encodedContentRuleList: blockRules
        )  contentRuleList, error in
            if let error = error 
                // Handle error
             else if let contentRuleList = contentRuleList 
                configuration.userContentController.add(contentRuleList)
             else 
                // Handle error
            
        

        super.init(frame: frame, configuration: configuration)
    

【讨论】:

以上是关于如何阻止外部资源加载到 WKWebView?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 WKWebview 从 iPad 的 Document 目录加载 javascript 和 css 资源?

在 WKWebview 中使用本地资源

IOS - 如何从 WKWebView 获取缓存的资源?

QWebView 不加载外部资源

WebKit webview (WKwebview) 无法加载应用目录之外的资源

WKWebView 确实从本地文档文件夹加载资源