如何删除 WKWebview cookie

Posted

技术标签:

【中文标题】如何删除 WKWebview cookie【英文标题】:How to delete WKWebview cookies 【发布时间】:2015-09-26 04:43:02 【问题描述】:

目前我正在这样做

    NSHTTPCookie *cookie;
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (cookie in [storage cookies])
    
        [storage deleteCookie:cookie];
    

但它不适用于 ios 8、64 位设备。

WKWebview 的干净 cookie 还有其他方法吗?任何帮助将不胜感激。谢谢。

【问题讨论】:

【参考方案1】:

Apple 为 iOS 9 发布了新的 API,因此现在我们可以使用以下代码删除为 WKWebView 存储的特定于域的 cookie,但这会仅适用于具有 iOS 版本 9的设备 稍后

WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore];
[dateStore
   fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
   completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records) 
     for (WKWebsiteDataRecord *record  in records) 
       if ( [record.displayName containsString:@"facebook"]) 
         [[WKWebsiteDataStore defaultDataStore]
             removeDataOfTypes:record.dataTypes
             forDataRecords:@[record]
             completionHandler:^
               NSLog(@"Cookies for %@ deleted successfully",record.displayName);
             
         ];
       
     
   
 ];

sn-p 以上肯定适用于 iOS 9 及更高版本。不幸的是,如果我们在 iOS 9 之前的 iOS 版本中使用 WKWebView,我们仍然必须坚持传统的方法并删除整个cookies存储如下。

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];

以下是 Swift 3 版本

let dataStore = WKWebsiteDataStore.default()
    dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  (records) in
        for record in records 
            if record.displayName.contains("facebook") 
                dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: [record], completionHandler: 
                    print("Deleted: " + record.displayName);
                )
            
        
    

还有 Swift 4:

let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  records in
  dataStore.removeData(
    ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
    for: records.filter  $0.displayName.contains("facebook") ,
    completionHandler: completion
  )

【讨论】:

使用这种方法只返回域级别,即 facebook.com ,它告诉我里面有 cookie。但我无法删除或检索单个项目。例如 facebook 内的会话 cookie。旧方法会将所有 cookie 扁平化为一个列表。这是设计使然还是我错过了什么。我找不到任何信息。 - @pankaj 您是否尝试过删除 WKWebsiteDataTypeSessionStorage 类型的记录? 遗憾的是,它被用作 cookie,在 safari 中的调试显示我有两个域被存储,还有一些其他项目正在使用 cookie、本地存储等。在 HTTPCookieStore 下,您会看到所有域的平面列表cookie 列表。我想要的这个会话 cookie 就在里面。但不是在通过新的 DataStore 请求时。但是,我确实看到了两个域项目。因此,我需要深入了解第二个级别。 @PankajGaikar 有没有办法从域中删除特定的 cookie? 请注意,WebKit API 必须在主线程上调用,这与 NSHTTPCookieStorage 不同。如果您在后台线程中清除 cookie,则需要坚持使用 NSHTTPCookieStorage。【参考方案2】:

Swift 3 版本的 Sarat 的回答:

let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  (records) in
    for record in records 
        if record.displayName.contains("facebook") 
            dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: [record], completionHandler: 
                print("Deleted: " + record.displayName);
            )
        
    

【讨论】:

【参考方案3】:

支持 iOS 11.0 及以上版本

以下解决方案对我很有效:

步骤 1. 从 HTTPCookieStorage 中删除 Cookie

第二步,从WKWebsiteDataStore获取数据记录并删除。

第 3 步。创建一个新的WKProcessPool

创建一个 WKWebView 扩展:

extension WKWebView 

    func cleanAllCookies() 
        HTTPCookieStorage.shared.removeCookies(since: Date.distantPast)
        print("All cookies deleted")

        WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  records in
            records.forEach  record in
                WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes, for: [record], completionHandler: )
                print("Cookie ::: \(record) deleted")
            
        
    

    func refreshCookies() 
        self.configuration.processPool = WKProcessPool()
    

用法:

override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(true)
        webView.cleanAllCookies()
        webView.refreshCookies()
    

【讨论】:

【参考方案4】:

这些选项都不适合我,但我找到了一个:

let config = WKWebViewConfiguration()
if #available(iOS 9.0, *) 
    config.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
 else 
     // I have no idea what to do for iOS 8 yet but this works in 9.


let webView = WKWebView(frame: .zero, configuration: config)

【讨论】:

使用此存储,您正在使用“私有模式”,其中 localStorage 和其他将不可用,因此您的 javascript 可能会失败,但是是的,它会擦除​​所有内容【参考方案5】:

在 iOS9 中:

//// Optional data
NSSet *websiteDataTypes
= [NSSet setWithArray:@[
                        WKWebsiteDataTypeDiskCache,
                        //WKWebsiteDataTypeOfflineWebApplicationCache,
                        WKWebsiteDataTypeMemoryCache,
                        //WKWebsiteDataTypeLocalStorage,
                        //WKWebsiteDataTypeCookies,
                        //WKWebsiteDataTypeSessionStorage,
                        //WKWebsiteDataTypeIndexedDBDatabases,
                        //WKWebsiteDataTypeWebSQLDatabases
                        ]];
//// All kinds of data
//NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
//// Date from
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
//// Execute
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^
    // Done
    NSLog(@"remove done");
];

【讨论】:

【参考方案6】:

除了清除共享cookie存储中的cookie之外,我会尝试清除缓存(NSURLCache)并丢弃WKWebView并使用新的WKProcessPool创建一个新的

【讨论】:

好吧,我很害怕,但这也不起作用。我在某处读到我也必须从设备中删除本地库,我也会尝试这样做。 如果你使用 WKProcessPool 技巧(来自***.com/questions/33156567/…)在多个 WKWebViews 之间共享 cookie,你需要像答案一样创建一个新的 WKProcessPool。【参考方案7】:

Swift 4 和更短的版本:

let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  records in
    dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
                         for: records.filter  $0.displayName.contains("facebook") ,
                         completionHandler: completion)

【讨论】:

【参考方案8】:

在所有现有答案的基础上,如果您尝试清除特定 WKWebView 实例“webView”的 cookie 和数据记录,而不是“默认”存储的 cookie 和数据记录,则可以使用以下内容:

let dataStore = webView.configuration.websiteDataStore
let cookieStore = dataStore.httpCookieStore
cookieStore.getAllCookies 
    $0.forEach  cookie in
        cookieStore.delete(cookie)
    

dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes())  records in
    records.forEach  record in
        dataStore.removeData(ofTypes: record.dataTypes, for: [record])  
    

【讨论】:

【参考方案9】:

现在 iOS 8.2 中似乎正在使用 NSHTTPCookieStorage 来根据需要正确清除 cookie。在打开基于 WKWebView 的登录之前,我已经发布了一个可以运行此代码的应用程序:

NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [storage cookies])

    [storage deleteCookie:cookie];

在 iOS 8.2 之前,网站会使用保存的 cookie 自动登录,现在它会正确要求用户重新登录。这一切都是在我没有向应用程序发送更新的情况下发生的。 :)

【讨论】:

这没什么意义,你的代码和我的代码是一样的,虽然我也试过这个代码。不,这对我也不起作用。 好的没问题我等你的回答 现在,我一无所知,不知道这里发生了什么,仍然会尝试一些解决方法..【参考方案10】:

Esqarrouth 的回答只是部分正确。 正确的 swift 版本是:

var libraryPath : String = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first!.path!
libraryPath += "/Cookies"
do 
    try NSFileManager.defaultManager().removeItemAtPath(libraryPath)
 catch 
    print("error")

NSURLCache.sharedURLCache().removeAllCachedResponses()

【讨论】:

【参考方案11】:

WKWebview 在 [NSHTTPCookieStorage sharedHTTPCookieStorage] 中不存储任何内容。

清除 WKWebsiteDataStore 将是解决此问题的方法。

对于使用WKwebview的IOS8,此方法不适用..

【讨论】:

【参考方案12】:

在 WKWebView 中,写入和读取需要一些时间,因此当您获取 cookie 时,您将获得更新的 cookie,但有时它会是旧的,并且您将在任何服务器请求上收到错误。我在 3 天内遇到了这个问题,

解决方案:无需在 WKWebsiteDataStore 中存储 cookie。

获取 cookie:

斯威夫特:

extension WKWebView 
private var httpCookieStore: WKHTTPCookieStore   return WKWebsiteDataStore.default().httpCookieStore 
func getCookies(for domain: String? = nil, completion: @escaping ([String : Any])->())  
        var cookieDict = [String : AnyObject]()
        httpCookieStore.getAllCookies  cookies in
            for cookie in cookies 
                if let domain = domain 
                    if cookie.domain.contains(domain) 
                        cookieDict[cookie.name] = cookie.properties as AnyObject?
                    
                 else 
                    cookieDict[cookie.name] = cookie.properties as AnyObject?
                
            
            completion(cookieDict)
        
    

目标-c:

-(void )getAllCookies

    NSMutableString *updatedCockies= [[NSMutableString alloc] init];
    if (@available(iOS 11.0, *)) 
        WKHTTPCookieStore *cookieStore = _webView.configuration.websiteDataStore.httpCookieStore;
        NSLog(@"cookieStore *********************: %@",cookieStore);
        [cookieStore getAllCookies:^(NSArray* cookies) 
            NSHTTPCookie *cookie;
            for(cookie in cookies)
               NSLog(@"%@",cookie)
            
            self->updatedCookie = updatedCockies;
            NSLog(@"cookie *********************: %@", self->updatedCookie);
        ];
    

每次你想要新的cookie,所以你需要写下面的代码: 鉴于夏皮奥

斯威夫特:

let config = WKWebViewConfiguration()
if #available(iOS 9.0, *) 
    config.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
 else 
     // I have no idea what to do for iOS 8 yet but this works in 9.


let webView = WKWebView(frame: .zero, configuration: config)

目标 C--

WKWebViewConfiguration *wkWebConfig = [WKWebViewConfiguration new];
    wkWebConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];


self.webView = [[WKWebView alloc] initWithFrame: CGRectZero
                                      configuration: wkWebConfig];

********每次你都会得到新的cookies********

【讨论】:

【参考方案13】:

斯威夫特 5

    /// old API cookies
    for cookie in HTTPCookieStorage.shared.cookies ?? [] 
        HTTPCookieStorage.shared.deleteCookie(cookie)
    
    /// URL cache
    URLCache.shared.removeAllCachedResponses()
    /// WebKit cache
    let date = Date(timeIntervalSince1970: 0)
    WKWebsiteDataStore.default().removeData(
        ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
        modifiedSince: date,
        completionHandler:)

【讨论】:

【参考方案14】:

Swift 版本:

var libraryPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomainMask.UserDomainMask, false).first!
libraryPath += "/Cookies"

do 
  let result = try NSFileManager.defaultManager().removeItemAtPath(libraryPath)
  print(result)
 catch 
  print("error")

NSURLCache.sharedURLCache().removeAllCachedResponses()

【讨论】:

这总是对我返回一个错误。我为NSSearchPathForDirectoriesInDomains 中的最后一个参数传递了true,它可以工作

以上是关于如何删除 WKWebview cookie的主要内容,如果未能解决你的问题,请参考以下文章

Swift 4 WKWebView cookie 获取和删除同步问题

更改 WKWebview 框架高度后如何删除 WKScrollView 内的空白区域?

如何从 WKWebview 中删除或隐藏 PDF 的页面计数器?

如何在swift 4中从WKWebView中的网页中删除DIV标签?

如何从 WKWebView 获取 cookie?

如何从 WKWebView 启用和获取 cookie?