UIWebView中的Facebook身份验证不会重定向回我站点上的原始页面,要求进行身份验证

TMC*_*TMC 21 mobile facebook ios facebook-social-plugins facebook-login

在我们的iOS应用程序中,我们有一个UIWebView,在我们的域上显示具有Facebook评论模块的Web内容.评论模块要求用户使用Facebook登录.当用户点击登录按钮时,他们将通过登录流程,但永远不会重定向回我们的页面.他们最终在FB拥有的页面上告诉用户"你现在已登录".

Repro步骤:

  1. 在iOS应用程序中创建UIWebView,并在您拥有的某个域上托管的页面上托管Facebook评论模块(例如http://foo.com/test.htm).
  2. 单击注释模块上的"登录"按钮,注意您将重定向到FB登录.
  3. 使用有效的FB凭据登录并观察会发生什么.

登录后(步骤3)我希望在成功验证后,您将被重定向回原始页面(例如http://foo.com/test.htm),以便继续进行交互.但是,这种情况并没有发生.

相反,你在FB拥有的页面上只是说"你现在已经登录"并且你被困在那里.没有重定向发生.

这确实是一个错误,还是我应该做些什么来确保重定向发生?

dth*_*lke 10

如果您只是支持iOS 8及更高版本,您可以使用WKWebView已经实现了@kabuko所描述的功能:

// Container view including the main WKWebView
var container : UIView?
var popupWebView : WKWebView?

override func viewDidLoad() {
    super.viewDidLoad()

    let prefs = WKPreferences()
    prefs.javaScriptEnabled = true
    // allow facebook to open the login popup
    prefs.javaScriptCanOpenWindowsAutomatically = true

    let config = WKWebViewConfiguration()
    config.preferences = prefs

    webView = WKWebView(frame: container.frame, configuration: config)
    webView?.UIDelegate = self
    webView?.navigationDelegate = self
}

// callback if the content of the webView wants to create a new window
func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    // create new popup webview and add it to the view hierarchy
    popupWebView = WKWebView(frame: container.frame, configuration: configuration)
    container.addSubview(popupWebView!)
    return popupWebView
}

func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
    // if the main webView loads a new page (e.g. due to succesful facebook login)
    // remove the popup
    if (popupWebView != nil) {
        popupWebView?.removeFromSuperview()
        popupWebView = nil
    }
}
Run Code Online (Sandbox Code Playgroud)


kab*_*uko 8

我已经看到类似的事情发生在其他网站的FB登录(例如Groupon),如果你加载它们UIWebView.如果这是同样的问题(我认为是这样),那因为Facebook打开了你怀疑的弹出窗口中的登录窗口.在普通浏览器上发生的事情是打开另一个窗口(弹出窗口)进行登录,然后当用户登录时,该登录窗口会回传到原始窗口,说它已登录.他们可能使用EasyXDM或类似的东西.似乎有几层沟通策略,包括Flash和postMessage.

在iOS(和Android)上,这应该意味着它最终会与之通信postMessage.如果您跟踪通过您的网址,UIWebView您应该会在最后看到类似的内容:

https://s-static.ak.fbcdn.net/connect/xd_proxy.php#<lots of stuff>&relation=opener&transport=postmessage&<lots more stuff>
Run Code Online (Sandbox Code Playgroud)

UIWebView不支持多个窗口,因此它不能再postMessage回到原始页面,因为它已不再加载.您可以做的是检测何时UIWebView尝试加载FB登录页面并将其加载到单独的页面中UIWebView.现在你有两个窗口可以使用.

不幸的是,这仍然不够,因为当FB页面上的JavaScript试图运行window.opener.postMessagewindow.parent.postMessage因为window.parentwindow.opener没有设置到适当的窗口时它不起作用.我不知道在iOS中这样做的好方法(相比之下,Android为此提供了适当的API).

我解决这个问题的方法是破解一个JavaScript对象来包装这些调用.就像是:

window.opener={};
window.opener.postMessage = function(data,url) {
    // signal your code in objective-c using some strategy
};
window.parent = window.opener;
Run Code Online (Sandbox Code Playgroud)

有几种方法可以从JavaScript调用Objective-C,包括官方文档中的这个.您可以将此代码注入我之前提到的静态FB登录页面stringByEvaluatingJavaScriptFromString:.我找不到一个好的时间来做这个,所以我只是在页面加载和调用之后注入它,doFragmentSend()这是静态页面上的FB JavaScript方法,通常在主体加载时被调用.

所以现在我们需要做的就是通过UIWebView调用将这些数据传递给原始数据postMessage.它看起来像这样:

NSString *post = [NSString stringWithFormat:@"window.postMessage('%@', '*');", data];
[webView stringByEvaluatingJavaScriptFromString:post];
Run Code Online (Sandbox Code Playgroud)

如果你现在还没有注意到,这是一个非常混乱的黑客,我可能不会推荐它,除非你别无选择,但它对我有用.


小智 5

我有同样的问题.我想,在Facebook登录后,UIWebView组件为空,其中没有html代码.我通过检查webViewDidFinishLoad函数上的UIWebView组件的内容解决了这个问题,并在我检测到Facebook登录导致白色(空屏幕)时重新加载其内容:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if ( [[webView1 stringByEvaluatingJavaScriptFromString:
           @"document.body.innerHTML"] isEqualToString:@""] ) {
        [webView1 loadRequest:request]; //Define request as you want
    }
}
Run Code Online (Sandbox Code Playgroud)