处理 SFSafariViewController 中的弹出窗口/选项卡

Posted

技术标签:

【中文标题】处理 SFSafariViewController 中的弹出窗口/选项卡【英文标题】:Handle popups/tabs in SFSafariViewController 【发布时间】:2016-09-14 18:59:50 【问题描述】:

我正在我的应用中实现 SoundCloud 登录流程。该应用程序在SFSafariViewController 中打开https://soundcloud.com/connectredirect_uri 使用我的应用程序的自定义 URL 方案来接收响应。它适用于直接 SoundCloud 登录,但在尝试使用其“使用 Google 登录”按钮时失败。

在 Safari 中,该按钮会打开一个带有 Google 登录页面的新选项卡(桌面上的弹出窗口),然后通过postMessage 与 SoundCloud 选项卡进行通信。如果您使用 ios Safari 应用程序,此登录流程可以正常工作,但在 SFSafariViewController 中失败(单击按钮会转到带有 Google 网址的白页:https://accounts.google.com/o/oauth2/auth?...)。

目前我的解决方法是建议使用 Google 的用户点击 SFSafariViewController 上的 Safari 图标以完成 Safari 应用程序中的登录流程,但我想知道是否有办法在不离开我的应用程序的情况下处理此问题。

【问题讨论】:

有什么更新吗?我们在这里使用 WKWebView 反对同样的问题——按下“使用 Google 登录”没有任何效果。这似乎是在 SoundCloud 的法庭上。可以添加soundcloud 作为标签吗? @DrewO'Meara 目前还没有解决方案。我只是根据具体情况告诉用户有关 Safari 的解决方法 吱吱吱***.com/questions/42079684/… 以下关于我在手头使用 google 令牌完成 SC 完成 oauth 的进展有什么想法吗? @DrewO'Meara 在下面看到我的评论 【参考方案1】:

好吧,如果我使用UIWebView,您可以在用户通过 Google 进行身份验证后从 google 获取最终的 oauth 响应。但是,我们如何将其转回 SoundCloud(例如 soundcloud.com/connect/via/google_plus/returning

- (void) webViewDidFinishLoad:(UIWebView*)inWebView 

    NSString* str = [inWebView stringByEvaluatingjavascriptFromString:@"document.getElementById('response-form-encoded').value"];
    if ( str.length > 0 ) 
        NSDictionary* params = parseURLParams( str );
        NSLog( @"%@", params );
    

输出:


    "access_token" = "ya2...<removed>...4g";
    authuser = 0;
    code = "4/sU_g7....<removed>...fnRELA";
    "expires_in" = 3600;
    "id_token" = "eyJhb...<removed>...DA";
    prompt = none;
    scope = "https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/plus.login+https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/plus.moments.write+https://www.googleapis.com/auth/plus.me+https://www.googleapis.com/auth/plus.profile.agerange.read+https://www.googleapis.com/auth/plus.profile.language.read+https://www.googleapis.com/auth/plus.circles.members.read";
    "session_state" = "c8703a085b885bbe8c8d0e29277b0c2fdf9c6c87..65aa";
    state = "392921654%7C0.288515904";
    "token_type" = Bearer;

启动 google 登录步骤的 URL 如下——为方便起见,我在下面解码了 URL 转义编码:

    https://accounts.google.com/o/oauth2/auth?client_id=984739005367.apps.googleusercontent.com&response_type=code token id_token gsession&scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.profile&state=425511939|0.2912748339&access_type=offline&request_visible_actions=http://schemas.google.com/AddActivity http://schemas.google.com/ListenActivity http://schemas.google.com/CreateActivity&after_redirect=keep_open&cookie_policy=single_host_origin&prompt=none&include_granted_scopes=true&proxy=oauth2relay751149297&redirect_uri=postmessage&origin=https://soundcloud.com&gsiwebsdk=1&authuser=0&jsh=m;/_/scs/apps-static/_/js/k=oz.gapi.en.TA32fes-0yU.O/m=__features__/am=AQ/rt=j/d=1/rs=AGLTcCOuWXPCbMjoOmrZx_gBsAG8J20NLA

【讨论】:

如果您使用iOS8 或更高版本,Apple 建议使用WKWebView 而不是UIWebView;这种方法仍然有效吗? 很好的问题@Koen——我们一直在使用WKWebView 并且正在重现相同的结果,除了我没有找到插入getElementById('response-form-encoded') 的点之前我用@ 找到它987654331@。我观察到的不同之处在于,WKWebView 在 google 身份验证后似乎就坐在那里,而UIWebView 进入了一个空白窗格(这是检查那里还有哪些响应数据的提示)。 应该,我正在将我们的代码改回WKWebView,并希望找到放置它的地方。问题是如何使用 google 令牌完成 SC 身份验证! 尝试将返回的值传递给https://soundcloud.com/connect/via/google_plus/returning?code=&lt;code&gt;&amp;state=&lt;state&gt;。我从googlePlusSigninCallback 中的https://a1.sndcdn.com/javascripts/base_mobile.js 中提取了这个。 首先我得到client_id is missing 错误,然后加上client_secret 我得到Request failed: method not allowed (405)。请参阅我对帖子的上述编辑,以查看 URI SC 告诉 Google 去。我们应该能够弄清楚这一点。

以上是关于处理 SFSafariViewController 中的弹出窗口/选项卡的主要内容,如果未能解决你的问题,请参考以下文章

SFSafariViewController:隐藏导航栏

使用 SFSafariViewController 下载文档

使用 SFSafariViewController 的主要优势是啥?

如何在 SwiftUI 中使用 SFSafariViewController?

SFSafariViewController 显示任何 URL 的空白屏幕

SFSafariViewController 关闭后的背景音频