2012-11-09 11 views
6

我々は持っている:
(1)FacebookのOAuthの機能(「FBウェブアプリ」)とFacebookのAPIベースのWebアプリケーション
(2)のiPad(「ブラウザ」)iOS 5とiOS 6のOAuthリクエストに対応してFacebookログインページを開くようにUIWebViewを取得するにはどうすればよいですか?

当社のUIWebViewベースのブラウザ目的は、Facebookのログインページを開いて、iPadのUIWebViewベースのブラウザ(2)内のFB Webアプリケーション(1)にサインインすることです。

ここで多少同様の問題があります:ユーザーがFacebookのフォームにログイン名とパスワードを入力した後
http://facebook.stackoverflow.com/questions/11337285/no-longer-able-to-login-to-ios-app-via-oauth-the-page-requested-was-not-found

はしかし、その質問の問題が起こります。私たちの問題は、Facebookのログインフォームを最初に表示させることができないということです。その質問に示唆されているように、アプリタイプを「Web」から「Native/Desktop」に変更することは役に立たなかった。

ステップ:
2.
3のOnClick JavaScriptがOAuthのを開始しようとすると、このページの「FBウェブアプリ」起動ボタン上のこのUIWebViewブラウザで
1.弊社のWebページ(シンプルなHTMLページ)、これは、FBウェブアプリ

現在の結果(問題)にサインインするのFacebookのログイン画面を開く必要があります - 私たちのウェブページが
変わらないままのiOS 5 +とiOS 6 +デバイス
オン
- FacebookのログインページはNです示さOT(私たちのウェブページがまだ表示されている)
のiOS 4.3で(期待通り動作します):
- Facebookのログインページをブラウザの同じUIWebView対象に開かれた(私たちのウェブページを置き換える)

期待される成果:
- Facebookログインページが表示され、ユーザはFacebookログイン&パスワード
を入力できます - iPadのSafariブラウザで起動した場合、iOS 5. +とiOS 6. +で動作します。 Facebookのログインページが別のタブで開く(対照的に、UIWebViewには別々のタブが存在しない)

質問です:どのように私はiOSの5+とiOS 6のOAuthリクエストに応じて、Facebookのログインページを開くには、UIWebViewを得ることができます+?

技術的な詳細は:

我々は

-(BOOL)webView(UIWebView*)webView shouldStartLoadWithRequest(NSURLREquest*)request navigationType:… 

内から異なるNSURLRequestフィールドをログと、私たちは「正しい」と「正しくない」行動のためのログにいくつかの違いに気付きます。ここでは、実行が私のために見てどのように流れるか:まず

、私は、www.facebook.comに「正しい」
要求、その後、いくつかの例は、iOSの4.3

を行く、OAuthのを開始するために、「FB Webアプリケーション」の起動ボタンを押してください/ダイアログ/ OAuthのm.facebook.com/login.phpする
要求をfbwebapp.comするには?...
要求?....
--here facebookでログインは、iOS 5.0

は、「incorrect1」
要求は?...
要求がm.facebookする
要求をfbwebapp.comするwww.facebook.com/dialog/oauthように見えます。 COM/login.php?...

そして、それはパラメータ
sqliteのエラーが続い
に...次m.facebook.com/login.php?...withの
--aたくさんかもしれ - さて、私は "申し訳ありませんが、何かが間違っていた"と思っています。

をfbwebapp.comするFacebookからGE(それは私がそれに遭遇したすべての最初の時間です)

のiOS 6.0「incorrect2」
www.facebook.com/dialog/oauthする要求?...
要求

-(void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error is invoked with error code -999

この動作は、iOSのバージョンによって異なります。しかし、一般的なケースは、m.facebook.com/login.php .. URLを取得するステップでエラーが発生するということです。しかし、それは私たちが検出できるすべてです。

私たちは一日中、その壁に頭を向けて解決策を探しています。うんざりする。
OAuthに対応してUIWebViewにFacebookのログインページを開くことができますか?

答えて

0

FBDialogクラスを使用して、ユーザーのログインを促します。次に、あなたのクラスはFBDialogDelegateプロトコルに準拠して、自分のクラスにこの関数を追加します

NSString *kRedirectURL = @"fbconnect://success"; 
NSString *kSDK = @"ios" ; 
NSString *kLogin = @"oauth"; 
NSString *kDialogBaseURL = @"https://m.facebook.com/dialog/"; 

NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
           AE_FACEBOOK_APPID, @"client_id", 
           @"user_agent", @"type", 
           kRedirectURL, @"redirect_uri", 
           @"touch", @"display", 
           kSDK, @"sdk", 
           nil]; 

NSString *loginDialogURL = [kDialogBaseURL stringByAppendingString:kLogin]; 

FBLoginDialog* loginDialog = [[FBLoginDialog alloc] initWithURL:loginDialogURL 
                loginParams:params 
                 delegate:self]; 
[loginDialog show]; 

:これは、ユーザーが任意ののUIWebViewの内部に記録されます。ログインが成功にので、アプリ内のWebViewを使用しています

-(void)fbDialogLogin: (NSString *)token expirationDate:(NSDate *)expirationDate{ 
    // Store the token and expiration date into the FB SDK 
    self.facebook.accessToken = token; 
    self.facebook.expirationDate = expirationDate; 
    // Then persist these so the SDK picks them up on next load 

    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 

[defaults setObject:self.facebook.accessToken forKey:ACCESS_TOKEN_KEY]; 
[defaults setObject:self.facebook.expirationDate forKey:EXPIRATION_DATE_KEY]; 
[defaults synchronize]; 
} 

HTH!

+0

、あなたはこのソリューションについての詳細を説明できますか?私はiOSの初心者ですが、すでにいくつかのFacebook SDKサンプルを試しています。 yaを参照してください – owlmsj

3

でしたか?

これはちょっとしたハックですが、iOS 6のUiWebViewのjs facebook sdk loginがやっと動作します。

どうすればいいですか?これは、純粋なJS + FacebookのJS SDK + UIWebViewデリゲート関数の処理ソリューションです。

JS - ファーストステップ)

ログインボタン(Facebookに接続するための)顔JSログイン/ OAuthのダイアログをトリガすること、この機能の例を呼び出します。

function loginWithFacebookClick(){ 

FB.login(function(response){ 
    //normal browsers callback 
}); 

} 

JS - 第二ステップ)

ユーザがWebページを読み込むたびに(FBの後に)authResponseChangeリスナを追加します。'とき

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
NSString *url = [[request URL] absoluteString]; 

//when user status == connected (has a access_token at facebook oauth response) 
if([url hasPrefix:@"https://m.facebook.com/dialog/oauth"] && [url rangeOfString:@"access_token="].location != NSNotFound) 
{ 
    [self backToLastPage]; 
    return NO; 
} 

return YES; 
} 

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 

NSString *url = [[webView.request URL] absoluteString]; 

if([url hasPrefix:@"https://m.facebook.com/dialog/oauth"]) 
{ 
    NSString *bodyHTML = [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"]; 

    //Facebook oauth response dead end: is a blank body and a head with a script that does 
    //nothing. But if you got back to your last page, the handler of authResponseChange 
    //will catch a connected status if user did his login and auth app 
    if([bodyHTML isEqualToString:@""]) 
    { 
     [self backToLastPage]; 
    } 
} 

} 

ので、第三ステップ) -

FB.Event.subscribe('auth.authResponse.Change', function(response){ 
//UIWebView login 'callback' handler 
var auth = response.authResponse; 
if(auth.status == 'connected'){ 
    //user is connected with facebook! just log him at your webapp 
} 
}); 

とアプリののUIWebViewデリゲートの機能を使用すると、FacebookのOAuthの応答

のObjective Cハンドラ]することができます。init())は、ユーザーの接続状態をキャッチしますユーザーを最後に読み込まれたページにリダイレクトすると、2番目のステップではFacebookのログインダイアログでユーザーアクションを処理します。

この回答で私が速すぎる場合は、私に相談してください! お手伝いをしてください。

4

だけ使用します。ここでは、このコード

if (![FBSDKAccessToken currentAccessToken]) 
{ 
    FBSDKLoginManager *manager = [[FBSDKLoginManager alloc]init]; 
    manager.loginBehavior = FBSDKLoginBehaviorWeb; 
    [manager logInWithReadPermissions:@[@"public_profile", @"email", @"user_friends"] handler: 
    ^(FBSDKLoginManagerLoginResult *result, NSError *error) { 

     NSLog(@"result.token: %@",result.token.tokenString); 
     NSLog(@"%@",result.token.userID); 
     NSLog(@"%hhd",result.isCancelled);  
    }]; 
} 

// manager.loginBehavior = FBSDKLoginBehaviorWeb;あなたは、誰もがグーグルでされた場合にはUIWebview

1

にログインfacebookを開くために必要なすべては、ここに私のために働いていたものですされています

-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)inType { 
    if ([request.URL.absoluteString containsString:@"m.facebook.com"]) { 
     if ([request.URL.absoluteString rangeOfString:@"back"].location == 0) { 
      [self.popUp removeFromSuperview]; 
      self.popUp = nil; 
      return NO; 
     } 
     if (self.popUp) { 
      return YES; 
     } 

     UIWebView *wv = [self popUpWebView]; 
     [wv loadRequest:request]; 
     return NO; 
    } 
    return YES; 
} 

- (UIWebView *) popUpWebView { 
    toolbar height 
    UIWebView *webView = [[UIWebView alloc] 
      initWithFrame:CGRectMake(0, 0, (float)self.view.bounds.size.width, 
        (float)self.view.bounds.size.height)]; 
    webView.scalesPageToFit = YES; 
    webView.delegate = self; 
    // Add to windows array and make active window 
    self.popUp = webView; 
    [self.view addSubview:webView]; 
    return webView; 
} 

- (void)webViewDidFinishLoad:(UIWebView *)webView { 

    if (self.popUp) { 
     NSError *error = nil; 
     NSString *jsFromFile = @"window.close=function(){window.location.assign('back://' + window.location);};"; 
     __unused NSString *jsOverrides = [webView 
       stringByEvaluatingJavaScriptFromString:jsFromFile]; 

     JSContext *openerContext = [self.webView 
       valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 
     JSContext *popupContext = [webView 
       valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 
     popupContext[@"window"][@"opener"] = openerContext[@"window"]; 
    } 


    //this is the secret sauce 
    if (webView == self.popUp 
      && [webView.request.URL.absoluteString containsString:@"m.facebook.com"] 
      && [[webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"] isEqualToString:@""]) { 
     [webView stringByEvaluatingJavaScriptFromString:@"eval(document.getElementsByTagName('script')[0].text)"]; 
    } 
} 

I snagged a bunch of this implementation from here

ウェブの実装に応じて、1つの追加ステップがある可能性があります。 Facebookのスクリプトは実際にwindow.close()を実行し、次にwindow.open()window.close()と実行します。ウェブ側では、このログインが完了した後、私のウィンドウ(つまり、ユーザにログインさせたいwebView)がwindow.close()コールをFacebook SDKから取得していたため、これは問題を引き起こしていました。私はFacebook SDKが、それが閉じるという新しいウィンドウを開くためにwindow.open()コールを呼び出すことを期待しているからです。

window.open()の機能をオーバーライドしていないため、window.open()を呼び出すとFacebookのSDKがウィンドウを閉じることを試みます。これはすべての種類の問題を引き起こす可能性がありますが、私はParseを使用しているので、window.localStoragenullに設定されていますので、すべての種類のエラーが発生していました。

このような何かがあなたのために起こっている場合は、それを修正するには、2つのオプションがあります:あなたがウェブコードの制御、および小型ハックのためのあなたのダウンを持っている場合は、

  1. window.close=function(){}
  2. でこれを投げます
  3. ウェブコードを管理していない場合は、popUp webViewと同じようにメインWebViewのwindow.closeにオーバーライドを追加するか、window.open関数をオーバーライドして別のpopUp(more detail here
0

UIWebViewのfacebookログイン方法。

Objective-Cの

使用taylorstine's answer。 彼は私の日を救った。ありがとうございますtaylorstine

私はスイフト3を使用していますので、私はちょうど下のコードをtaylorstineの答えから変換しました。

スウィフト3.

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool { 

    if let _ = request.url?.absoluteString.range(of: "m.facebook.com") { 
     if let _ = request.url?.absoluteString.range(of: "back"){ 
      self.popUp?.removeFromSuperview() 
      self.popUp = nil 
      return false 
     } 

     if let _ = self.popUp { 
      return true 
     } 

     let wv = popUpWebView() 
     wv.loadRequest(request) 

     return false 
    } 

    return true 
} 

func popUpWebView() -> UIWebView { 

    let webView = UIWebView(frame: self.view.frame) 

    webView.delegate = self 
    self.popUp = webView 
    self.view.addSubview(webView) 

    return webView 
} 

func webViewDidFinishLoad(_ webView: UIWebView) { 
    if let _ = self.popUp { 

     let jsFromFile = "window.close=function(){window.location.assign('back://' + window.location);};" 

     let _ = webView.stringByEvaluatingJavaScript(from: jsFromFile) 

     let openerContext = self.webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext 

     let popupContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext 

     popupContext.setObject("opener", forKeyedSubscript: "window" as (NSCopying & NSObjectProtocol)!) 
     popupContext.setObject(openerContext.objectForKeyedSubscript("window"), forKeyedSubscript: "opener" as (NSCopying & NSObjectProtocol)!) 

    } 

    if webView == self.popUp 
     && (webView.request?.url?.absoluteString.range(of:"m.facebook.com") != nil) 
     && webView.stringByEvaluatingJavaScript(from: "document.body.innerHTML") == "" { 

     webView.stringByEvaluatingJavaScript(from: "eval(document.getElementsByTagName('script')[0].text)") 

    } 

} 
関連する問題