iOS 個(gè)性化安裝的實(shí)踐一 Safari Cookie互通

  • Safari Cookie互通流程大致如下:

    1. 用戶使用Safari瀏覽wap,wap將個(gè)性化信息寫入cookie(取名要跟客戶端約定好,在demo中偶用testcookie)
    2. 用戶跳出wap進(jìn)入Apple Store下載app并啟動(dòng)運(yùn)行
    3. 初次運(yùn)行,初始化一個(gè)透明Safari(iOS10有新的約束,詳情看下面)
    4. Safari訪問(wèn)同一域名獲取cookie,并通過(guò)openURL(application:openURL:options:)回傳給app
    5. app拿到瀏覽器數(shù)據(jù)后,銷毀對(duì)應(yīng)Safari
  • iOS11 SFAuthenticationSession獲取cookie跟使用SFSafariViewController的流程大致相同,如下:

    1. 用戶使用Safari瀏覽wap,wap將個(gè)性化信息寫入cookie(取名要跟客戶端約定好,在demo中偶用testcookie)
    2. 用戶跳出wap進(jìn)入Apple Store下載app并啟動(dòng)運(yùn)行
    3. 初次運(yùn)行,初始化一個(gè)SFAuthenticationSession的實(shí)例authSession并需要strong持有(因?yàn)檫@個(gè)實(shí)例會(huì)被釋放,授權(quán)提示一閃而過(guò),讓你看看就好 ( ?? ?) ,就是這么驕傲放縱)
    4. authSession訪問(wèn)同一域名進(jìn)行身份認(rèn)證獲取cookie,并通過(guò)completionHandler回傳給app
    5. 拿到cookie后,訪問(wèn)的wap頁(yè)面會(huì)自行退出,但需要注意的是:若未拿到cookie,wap頁(yè)面需要人為操作才能消失,所以在沒(méi)有有效cookie,wap也要調(diào)用URL Schemes

對(duì)比發(fā)現(xiàn),其實(shí)兩個(gè)的差別很小,就是3.4.5這里稍稍不同,而wap代碼用同一份即可,這點(diǎn)還是很欣慰的,老淚縱橫呀,有木有,但是其實(shí)體驗(yàn)真心算不上好,感覺(jué)效果也就iOS9這一版本能讓人稍稍有點(diǎn)安慰

好了,不吹水了,咱們開(kāi)始正式的實(shí)踐操作


  1. 初始化一個(gè)Safari并訪問(wèn)同一個(gè)域名,這里偶在本地進(jìn)行測(cè)試,所帶Schemes為openURL所對(duì)應(yīng)的URL Schemes,真的使用中無(wú)需這個(gè)參數(shù)
self.safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:@"http://localhost/HelloPHP/index.html?Schemes=test1.liya"]];
self.safariVC.delegate = self;

2.接下來(lái)這步比較重要,為了讓用戶無(wú)感,Safari應(yīng)該是透明的,而這在iOS9的操作大部分如下:

self.safariVC.view.alpha = 0.0;
self.safariVC.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:self.safariVC animated:YES completion:nil];

但是在iOS10后就不被允許了(上面代碼會(huì)發(fā)現(xiàn)并未完成訪問(wèn)域名等操作),首先,最低透明度必須至少0.05,其次,跟window不可無(wú)重疊區(qū)域,具體可查閱review 5.1.1

SafariViewContoller must be used to visibly present information to users; the controller may not be hidden or obscured by other views or layers. Additionally, an app may not use SafariViewController to track users without their knowledge and consent.

現(xiàn)一般將Safari作為子控制器進(jìn)行添加,完整初始代碼如下

if ([LYSystem systemVersion] >= 9 && [LYSystem systemVersion] < 11) {
        self.safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:@"http://localhost/HelloPHP/index.html?Schemes=test1.liya"]];
        self.safariVC.delegate = self;
        self.safariVC.view.alpha = 0.05;
        [self addChildViewController:self.safariVC];
        self.safariVC.view.frame = CGRectMake(0.0, 0.0, 0.5, 0.5);
        [self.view insertSubview:self.safariVC.view atIndex:0];
        [self.safariVC didMoveToParentViewController:self];
    }

3.接下來(lái)就到了最重要的個(gè)性化數(shù)據(jù)獲取啦(AppDelegate.m),對(duì)其中url進(jìn)行解析判斷即可

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    NSLog(@"openURL = %@", url);
    return YES;
}

4.成功拿到數(shù)據(jù)后記得銷毀Safari,實(shí)際使用過(guò)程中同時(shí)也要考慮到超時(shí)的情況,可能獲取cookie失敗(demo只進(jìn)行簡(jiǎn)單成功的處理)

- (void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully {
    if (didLoadSuccessfully) {
        [self.safariVC willMoveToParentViewController:nil];
        [self.safariVC.view removeFromSuperview];
        [self.safariVC removeFromParentViewController];
        self.safariVC = nil;
    }
}

  • iOS11 SFAuthenticationSession 使用
    1.初始化一個(gè)SFAuthenticationSession并訪問(wèn)同一個(gè)域名,這一步類似
if ([LYSystem systemVersion] >= 11) {
        self.authSession = [[SFAuthenticationSession alloc] initWithURL:[NSURL URLWithString:self.urlStr] callbackURLScheme:nil completionHandler:^(NSURL * _Nullable callbackURL, NSError * _Nullable error) {
            NSLog(@"callbackURL = %@", callbackURL);
            NSLog(@"error = %@", error.description);
            self.authSession = nil;
        }];
        [self.authSession start];
    }
  1. 跟SFSafariViewController數(shù)據(jù)獲取的地方不同,在回調(diào)completionHandler block中callbackURL攜帶數(shù)據(jù),在error為nil時(shí)對(duì)其解析即可
  2. 用SFAuthenticationSession,會(huì)跳出一個(gè)授權(quán)頁(yè)面,選擇Cancel時(shí),completionHandler會(huì)收到error code=1的錯(cuò)誤,進(jìn)行授權(quán)確認(rèn)后,才進(jìn)行域名訪問(wèn),并對(duì)應(yīng)進(jìn)行處理
授權(quán)頁(yè)
授權(quán)后
  1. 到了這里,偶們也發(fā)現(xiàn)了,這個(gè)跟SFSafariViewController表現(xiàn)有所差距,滿滿的存在感,什么無(wú)感呀,扯淡,所以要解決兩點(diǎn),就是授權(quán)彈框提示隱藏并自行執(zhí)行繼續(xù)操作,還有訪問(wèn)域名頁(yè)面隱藏
    4.1 授權(quán)彈框
    每次請(qǐng)求都會(huì)彈出授權(quán)窗口,是可忍孰不可忍,跟蹤后發(fā)現(xiàn)授權(quán)窗口為SFBrowserRemoteViewController,并且訪問(wèn)頁(yè)面SFAuthenticationViewController以子控制器將其進(jìn)行添加,理所當(dāng)然以為可以類似切換APP桌面icon的彈框一樣,hook后不彈框并進(jìn)行允許操作,最后未實(shí)現(xiàn)(各種實(shí)驗(yàn)過(guò)程就不說(shuō)了),這一點(diǎn)會(huì)繼續(xù)探索(這一步希望有了解的可以告訴偶耶)
    4.2 域名訪問(wèn)頁(yè)面
    看頁(yè)面展示形式,比較明顯的模態(tài)跳轉(zhuǎn),想到的是在present前,改變頁(yè)面的一些屬性進(jìn)行處理,hook presentViewController:animated:completion:方法
+ (void)load {
    if ([LYSystem systemVersion] >= 11) {
        [UIViewController liya_swizzleMethod:@selector(presentViewController:animated:completion:) withMethod:@selector(liya_presentViewController:animated:completion:) error:nil];
    }
}

當(dāng)發(fā)現(xiàn)是授權(quán)顯示頁(yè)面時(shí),將其透明度改為0等其他操作即可實(shí)現(xiàn)web無(wú)感訪問(wèn)

- (void)liya_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
    Class SFAuthenticationViewController = NSClassFromString(@"SFAuthenticationViewController");
    if (SFAuthenticationViewController && [viewControllerToPresent isKindOfClass:SFAuthenticationViewController]) {
        viewControllerToPresent.view.alpha = 0.0;
        viewControllerToPresent.view.frame = CGRectZero;
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    }
    [self liya_presentViewController:viewControllerToPresent animated:flag completion:completion];
}

  • 用于測(cè)試的靜態(tài)網(wǎng)頁(yè)
    由于簡(jiǎn)單的測(cè)試,所以就不麻煩相關(guān)后臺(tái)人員,自行寫個(gè)簡(jiǎn)單的本地靜態(tài)頁(yè)面即可,這里推薦下PhpStorm 或者 WebStorm,使用方法自行g(shù)oogle喲,還是挺方便的。。。偶用于實(shí)踐的靜態(tài)頁(yè)面代碼相當(dāng)簡(jiǎn)單(不能添加附件,只能鏈接網(wǎng)址,這樣還要把這么一份小文件放入云盤中,實(shí)在麻煩,所以直接代碼全貼出來(lái)啦),只有如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width">
    <title>Liya測(cè)試叮叮咚</title>
</head>

<body>
<script>
    var cookie = document.cookie;
    var testcookies = cookie.match(/testcookie=(\w+)/);
    var testcookie;

    if (testcookies) {
        testcookie = testcookies[1];
        document.writeln("當(dāng)前cookie " + testcookie + '.');
    } else {
        document.writeln("當(dāng)前沒(méi)有cookie,輸入一個(gè) ");
        testcookie = "";
    }

    function getParameterByName(name) {
        var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
        return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
    }

    var Schemes = getParameterByName("Schemes");
    if (Schemes) {
        if (testcookie.length > 0) {
            location.href = Schemes+"://testcookie/" + testcookie;
        } else  {
            location.href = Schemes+"://";
        }
    }

    function saveTestcookie() {
        document.cookie = 'testcookie=' + document.getElementById('testcookie').value + ';max-age=3600';
        location.reload();
    }

</script>

<input type="text" id="testcookie">
<input type="submit" id="submit_cookie" value="新cookie保存" onclick="saveTestcookie();">

</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • HTTP cookie(也稱為web cookie,網(wǎng)絡(luò)cookie,瀏覽器cookie或者簡(jiǎn)稱cookie)是網(wǎng)...
    留七七閱讀 18,377評(píng)論 2 71
  • 一、基礎(chǔ)知識(shí)篇:Http Header之User-AgentUser Agent中文名為用戶代理,是Http協(xié)議中...
    iPhone閱讀 16,258評(píng)論 0 13
  • 今天webryan給team做了一個(gè)關(guān)于HTTP cookie的分享,從各個(gè)方面給大家介紹一下大家耳熟能詳?shù)腃oo...
    秒贊不是偶然閱讀 8,812評(píng)論 0 20
  • 任何為人稱道的美麗,都不及第一次遇見(jiàn)時(shí)的你! 太多的相遇讓人措手不及,太多的開(kāi)始讓我們不知所措,太多的過(guò)程讓我們百...
    在成長(zhǎng)的娟娟閱讀 1,394評(píng)論 9 13
  • 每一個(gè)經(jīng)歷過(guò)春運(yùn)的人,特別是坐過(guò)去往北上廣深的綠皮火車的人,想必都會(huì)贊同: 只有親身體驗(yàn)一下被擁擠的人流堵在車廂...
    猶俏閱讀 198評(píng)論 0 0

友情鏈接更多精彩內(nèi)容