Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when redirect with code 302, WKWebView cannot set cookie

Tags:

ios

wkwebview

I sent request to url1. url1 will redirect to url2 with cookie. url2 is for authorization. And I get code "302 found", which is correct. But when url2 redirect back to url1, the cookie lost. This results my request keeping redirect to url2, looping until failed.

Does any one met this kind of problem and know a solution? Thanks in advance.

This is a WKWebView problem. UIWebView will work fine. But somehow, I need to change to use WKWebView.

I already tried many solutions, such as Can I set the cookies to be used by a WKWebView?. These methods could handle the cookie in same domain. My problem is url1 and url2 have different domains. When redirect, the cookie is missing, which made the authorization failed, and resulted in looping between url1 and url2.

Does anybody met this problem and found out a workaround? Thanks in advance.

like image 341
T. W Avatar asked Jun 15 '17 20:06

T. W


3 Answers

Unfortunately, there is no official support for handling 302 redirect response in WKWebView.I came across the same issue too.There is a way to work around but may take some risks and not elegant.

  1. Override the WKWebView.load(_ request: URLRequest) and use URLSession to make the request instead.
  2. Make sure your URLSession can deal with 302 redirect by yourself which means you need to implement func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) to specify that you don't want the URLSession to handle 302 redirect automatically.
  3. Once you get the 302 response using URLSession the attached cookie will be set to HTTPCookieStorage.shared automatically.And then make a new request with those cookies and the url of response header field Location by WKWebView itself.

The code sample is Here.I subclass WKWebView and also deal with cookies in the most case including your 302 redirect case.If it works for you, please give me a star thx!

It is a really a hack way and be careful if you want use it in product.

like image 147
Xingxing Avatar answered Oct 13 '22 16:10

Xingxing


If you need subsequent requests from 'url2' to have their cookies set, you can try using 'WKUserScript' to set the values programmatically via javascript at document start like so:

WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc] 
    initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"
    injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];

However, if you require your cookies to be set on the initial load request, you can set them on NSMutableURLRequest like so:

WKWebView * webView = /*initialization stuff*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"YOUR URL"]];
[request addValue:@"TestCookieKey1=TestCookieValue1;TestCookieKey2=TestCookieValue2;" forHTTPHeaderField:@"Cookie"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];

You can combine above two techniques to transfer cookie values from Native environment to WebView environment.

You can refer to this link for more advanced information on cookies.

like image 4
tek3 Avatar answered Oct 13 '22 16:10

tek3


Maybe late to the party, but I faced something pretty close to the above question last week and also from my side I concluded that for some reason cookies on 302 response are not handled correctly by WKWebView.

If your problem is similar to the one i'm facing with:

you need to pass some cookies from a redirect required for a subsequent authentication stage

Then you can easily interchange your WKWebView with the one I provided into this gist.

and use it like follow:

let myWebView = SAWKWebView(frame: .zero)
...
myWebView.load(aRequest, handleRedirect: true, cookies: [myCookies])

cookies is not required and can be nil, depending on your setup.

SAWKWebView class inheriting from WKWebView and workaround the above problem by using directly URLSession and its delegate.

This way I could rely into a sufficient and safe way to break into the response 302 (aka redirect) and handle cookies manually with HTTPStorageCookie without relying onto javascript and document since in my experience it doesn't always work reliable.

Once the required redirect is performed I render the content as HTML and continue as needed.

like image 2
valvoline Avatar answered Oct 13 '22 15:10

valvoline