是否可以使用UIWebView的sharedHTTPCookieStorage手动设置cookie?


74

我在iOS应用程序内部具有Webview,这些Webview要求对身份验证cookie进行正确的身份验证。我正在寻找一种在iOS应用程序的Webview中设置cookie的方法,而不必发出出站请求来设置cookie,因为我已经在客户端上拥有身份验证信息。

这篇文章向我们展示了UIWebView cookie的存储位置。

现在,我正在加载一个隐藏的Web视图以发出出站请求,但希望不必通过外部请求来设置简单的Cookie。

Answers:


139

是的,您可以这样做。首先,在applicationDidBecomeActive中添加此行

[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];

cookieAcceptPolicy在应用程序之间共享,并且可以在不知情的情况下进行更改,因此,您需要确保每次应用程序运行时都具有所需的接受策略。

然后,设置cookie:

NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"testCookie" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"someValue123456" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];

// set expiration to one month from now or any NSDate of your choosing
// this makes the cookie sessionless and it will persist across web sessions and app launches
/// if you want the cookie to be destroyed when your app exits, don't set this
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];

NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];

此Cookie的名称为testCookie,值someValue123456,并将与任何http请求一起发送到www.example.com。

有关设置Cookie的一个大警告,请在此处查看我的问题!

应用程序退出时未保存NSHTTPCookieStorage状态。有明确的知识/文档吗?


NSHTTPCookieStorage当然可以完全实现持久性cookie存储。只需在服务器端正确设置cookie生存期即可。
直到

1
鲍尔,我们最终采用了这个解决方案,该解决方案非常接近您的答案:lists.apple.com/archives/Webkitsdk-dev/2003/Sep/msg00003.html
Mauvis Ledford

1
@ mauvis-ledford您如何将创建的cookie分配给uiwebview?
铭耀

11
Cookie不与Web视图相关联,它与对特定URL的HTTP请求相关联。任何HTTP请求,无论是直接从您的代码或网页视图会使用任何存储在NSHTTPCookieStorage
kball

3
有人可以确认这仍然有效吗?我在NSHTTPCookieStorage中有cookie,但是它们似乎无法用于我的UIWebView中运行的javascript。我使用Safari的网络检查器查看了Cookie存储区,它是空的。任何帮助,不胜感激。iOS 10.3
Colin Whitmarsh

14

编辑:适应已编辑的问题

NSHTTPCookieStorage有一个-setCookies:forURL:mainDocumentURL:方法,因此最简单的方法是使用NSURLConnection和实现-connection:didReceiveResponse:,提取cookie并将其填充到cookie jar中:

- ( void )connection: (NSURLConnection *)connection
          didReceiveResponse: (NSURLResponse *)response
{
    NSHTTPURLResponse        *httpResponse = (NSHTTPURLResponse *)response;
    NSArray                  *cookies;

    cookies = [ NSHTTPCookie cookiesWithResponseHeaderFields:
                             [ httpResponse allHeaderFields ]];
    [[ NSHTTPCookieStorage sharedHTTPCookieStorage ]
            setCookies: cookies forURL: self.url mainDocumentURL: nil ];
}

(你也可以简单地提取NSDictionary从对象NSHTTPCookieproperties,然后写字典中的磁盘。读它放回是那么容易,因为使用NSDictionary-dictionaryWithContentsOfFile:,然后创建与cookie-initWithProperties:)。

然后,您可以在需要时将Cookie从存储中拉回:

- ( void )reloadWebview: (id)sender
{
    NSArray                 *cookies;
    NSDictionary            *cookieHeaders;
    NSMutableURLRequest     *request;

    cookies = [[ NSHTTPCookieStorage sharedHTTPCookieStorage ]
                cookiesForURL: self.url ];
    if ( !cookies ) {
        /* kick off new NSURLConnection to retrieve new auth cookie */
        return;
    }

    cookieHeaders = [ NSHTTPCookie requestHeaderFieldsWithCookies: cookies ];
    request = [[ NSMutableURLRequest alloc ] initWithURL: self.url ];
    [ request setValue: [ cookieHeaders objectForKey: @"Cookie" ]
              forHTTPHeaderField: @"Cookie" ];

    [ self.webView loadRequest: request ];
    [ request release ];
}

1
无需通过这种方式手动管理NSHTTPCookieStorage。每当URL加载系统使用HTTP并将cookie接受策略设置为接受cookie时,都会自动管理NSHTTPCookieStorage-如果在响应标头中设置了cookie,则存储cookie,并在发送请求时为存储的cookie设置标头。
kball 2011年

当然。当然,这种方法意味着开发人员不知道随每个请求保存和发送了哪些cookie,如果站点设置了不需要的跟踪cookie,这可能是不希望的。尽管通常仅在Mac OS X上使用NSHTTPCookieStorage也是一个重量级的解决方案。例如,请参阅:cocoabuilder.com/archive/cocoa/…–
更加紧张

1
欣赏长答案,尽管设置单个cookie似乎需要大量工作。我们最终这样做:lists.apple.com/archives/Webkitsdk-dev/2003/Sep/msg00003.html
Mauvis Ledford

8

在Swift 3中,所有键都包装在HTTPCookiePropertyKeystruct中:

let cookieProperties: [HTTPCookiePropertyKey : Any] = [.name : "name",
                                                       .value : "value",
                                                       .domain : "www.example.com",
                                                       .originURL : "www.example.com",
                                                       .path : "/",
                                                       .version : "0",
                                                       .expires : Date().addingTimeInterval(2629743)
                                                      ]

if let cookie = HTTPCookie(properties: cookieProperties) {
    HTTPCookieStorage.shared.setCookie(cookie)
}

谢谢,我是提供了一个URL对象不是一个字符串domainoriginURL
拉杜Ursache

1

有必要解决iOS 10引入的cookie限制,这会使它们在不同进程中不可见。

这意味着在具有多处理能力的设备上,Web视图是与您的应用程序不同的过程,这意味着您的“应用程序”会话不再自动传输到Web视图。

因此,从本质上讲,您将需要这样做(即使以前的海报是对的,它也可以在iOS10之前自动运行)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.