karosLi / KKJSBridge

一站式解决 WKWebView 支持离线包,Ajax/Fetch 请求,表单请求和 Cookie 同步的问题 (基于 Ajax Hook,Fetch Hook 和 Cookie Hook)
MIT License
693 stars 120 forks source link

关于 cookie 获取失败的问题 #19

Closed lichanghong closed 4 years ago

lichanghong commented 4 years ago

再次请教大神个问题 webview初始化之前配置cookie,js是可以获取cookie的,但是当webview里加上这句,js就获取不到cookie了: _jsBridgeEngine = [KKJSBridgeEngine bridgeForWebView:self];

lichanghong commented 4 years ago

大神我找到原因了,KKJSBridgeEngine 的这句 代码注掉就OK了: [self.webView.configuration.userContentController removeAllUserScripts]; 但是这句不应该注掉,而是应该移除KK组件里注册的UserScripts,您看下怎么可以优化下

karosLi commented 4 years ago

嗯,是的,是不应该移除所有的,只是这里没有api去移除指定的userScript。

另外你说的 cookie 获取不到,是什么场景下呢,有 demo 吗?我在代码上有针对每次请求设置ajax cookie的。 image

lichanghong commented 4 years ago

有一种场景是这样的,在app启动的时候设置cookie [ZRWebView configCookieWithDictionary:@{@"logined":@"1"} AndCookieDomain:@"http://10.30.115.250:8800/js.html"];

方法实现是这样的:

当webview初始化方法之前,从NSHTTPCookieStorage获取到cookie放到WKUserScript 里,这样H5就可以获取到cookie了。(必须是webview初始化之前设置才能拿到cookie) 例如:

karosLi commented 4 years ago

那你初始化webview之后,又会改变cookie吗?

karosLi commented 4 years ago

能否说一下一个完整的使用流程(可以是基于业务)。

lichanghong commented 4 years ago

初始化webview之后不会改变cookie,使用流程:app启动的时候设置NSHTTPCookieStorage,比如登陆状态@{@"logined":@"1"} ,webview实例化的时候取出来,通过WKUserScript把cookie放到webview,这样H5就可以读取logined字段的cookie了。 然而这句:[self.webView.configuration.userContentController removeAllUserScripts];会把我设置的remove掉,所以获取不到了

karosLi commented 4 years ago

因为按理说,这里会把NSHTTPCookieStorage里 cookie自动转成javascript并执行,而不需要你那边手动添加自己的脚本,你可以在这里调试看下。

image

lichanghong commented 4 years ago

大神,您发的图片没展示出来😄

karosLi commented 4 years ago

你可以在这个方法里调试下

+ (NSString *)ajaxCookieScripts {
    NSMutableString *cookieScript = [[NSMutableString alloc] init];
    for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
        // Skip cookies that will break our script
        if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
            continue;
        }
        // Create a line that appends this cookie to the web view's document's cookies
        [cookieScript appendFormat:@"document.cookie='%@=%@;", cookie.name, cookie.value];
        if (cookie.domain || cookie.domain.length > 0) {
            [cookieScript appendFormat:@"domain=%@;", cookie.domain];
        }
        if (cookie.path || cookie.path.length > 0) {
            [cookieScript appendFormat:@"path=%@;", cookie.path];
        }
        if (cookie.expiresDate) {
            [cookieScript appendFormat:@"expires=%@;", [[self cookieDateFormatter] stringFromDate:cookie.expiresDate]];
        }
        if (cookie.secure) {
            // 只有 https 请求才能携带该 cookie
            [cookieScript appendString:@"Secure;"];
        }
        if (cookie.HTTPOnly) {
            // 保持 native 的 cookie 完整性,当 HTTPOnly 时,不能通过 document.cookie 来读取该 cookie。
            [cookieScript appendString:@"HTTPOnly;"];
        }
        [cookieScript appendFormat:@"'\n"];
    }

    return cookieScript;
}
ZhangKejun commented 4 years ago

你可以在这个方法里调试下

+ (NSString *)ajaxCookieScripts {
    NSMutableString *cookieScript = [[NSMutableString alloc] init];
    for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
        // Skip cookies that will break our script
        if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
            continue;
        }
        // Create a line that appends this cookie to the web view's document's cookies
        [cookieScript appendFormat:@"document.cookie='%@=%@;", cookie.name, cookie.value];
        if (cookie.domain || cookie.domain.length > 0) {
            [cookieScript appendFormat:@"domain=%@;", cookie.domain];
        }
        if (cookie.path || cookie.path.length > 0) {
            [cookieScript appendFormat:@"path=%@;", cookie.path];
        }
        if (cookie.expiresDate) {
            [cookieScript appendFormat:@"expires=%@;", [[self cookieDateFormatter] stringFromDate:cookie.expiresDate]];
        }
        if (cookie.secure) {
            // 只有 https 请求才能携带该 cookie
            [cookieScript appendString:@"Secure;"];
        }
        if (cookie.HTTPOnly) {
            // 保持 native 的 cookie 完整性,当 HTTPOnly 时,不能通过 document.cookie 来读取该 cookie。
            [cookieScript appendString:@"HTTPOnly;"];
        }
        [cookieScript appendFormat:@"'\n"];
    }

    return cookieScript;
}

大佬,我打了断点,你这个ajaxCookieScripts的方法不执行;我现在的问题是第一个请求需要一个原生设置在NSHTTPCookieStorage里面的cookie,但我运行发现第一个请求不会执行到原生这边来

karosLi commented 4 years ago

你的第一个请求是通过 loadRequest 来加载请求的吗,你的请求链接是什么? image

ZhangKejun commented 4 years ago

你的第一个请求是通过 loadRequest 来加载请求的吗,你的请求链接是什么? image

是H5页面里面的ajax请求,我在打开wk之前已经将cookie设置在了NSHTTPCookieStorage里面;这个ajax请求后端会检测这个cookie,目前抓包看,没有携带过去;

ZhangKejun commented 4 years ago

你的第一个请求是通过 loadRequest 来加载请求的吗,你的请求链接是什么? image

是H5页面里面的ajax请求,我在打开wk之前已经将cookie设置在了NSHTTPCookieStorage里面;这个ajax请求后端会检测这个cookie,目前抓包看,没有携带过去;

你之前的mater分支的代码,开启ajax之后是可以的,但开启后访问其他的有问题,所以你建议我用beta版本。大佬,看方便看下邮件,能否加下我的微信。想请教一下

karosLi commented 4 years ago

已经加了

karosLi commented 4 years ago

这个问题是没有使用 KKWebView 的缘故,cookie 的同步在之前的版本里,需要结合 KKWebView 来一起使用。1.1.5-beta9 之后的版本已经可以单独使用 Bridge 来进行同步 cookie 了。