2012-11-09 6 views
6

हम:
(1) फेसबुक OAuth कार्यक्षमता ("अमेरिकन प्लान वेब अनुप्रयोग") के साथ फेसबुक एपीआई आधारित वेब अनुप्रयोग
(2) iPad ("ब्राउज़र")आईओएस 5 और आईओएस 6 पर ओएथ अनुरोध के जवाब में फेसबुक लॉगिन पेज खोलने के लिए मैं UIWebView कैसे प्राप्त कर सकता हूं?

हमारे पर UIWebView आधारित ब्राउज़र आईपैड पर UIWebView- आधारित ब्राउज़र (2) के अंदर एफबी वेब ऐप (1) में साइन इन करने के लिए फेसबुक लॉगिन पेज खोलना है।

यहाँ में कुछ ऐसी ही समस्या है:
http://facebook.stackoverflow.com/questions/11337285/no-longer-able-to-login-to-ios-app-via-oauth-the-page-requested-was-not-found

हालांकि, उस प्रश्न के जारी होने के बाद उपयोगकर्ता के लिए लॉग इन और फेसबुक के रूप में पासवर्ड में प्रवेश करती है होता है। हमारी समस्या यह है कि हम पहले स्थान पर प्रदर्शित फेसबुक लॉगिन फॉर्म नहीं प्राप्त कर सकते हैं। उस प्रश्न में सुझाए गए अनुसार, "वेब" से "मूल/डेस्कटॉप" तक ऐप प्रकार को बदलना, मदद नहीं करता था।

कदम:
1. इस UIWebView ब्राउज़र "अमेरिकन प्लान वेब अनुप्रयोग" इस पृष्ठ
3. OnClick जावास्क्रिप्ट OAuth आरंभ करने का प्रयास पर लांच बटन पर
2. क्लिक के साथ ओपन हमारे वेब पेज (सरल HTML पृष्ठ), जो अमेरिकन प्लान वेब एप्लिकेशन

वर्तमान परिणाम (मुद्दे) में प्रवेश करने के लिए फेसबुक के लॉगिन स्क्रीन खोलने चाहिए: - हमारी वेब पेज में कोई बदलाव नहीं
रहता
आईओएस 5 + और आईओएस 6 + उपकरणों
पर - फेसबुक लॉगिन पेज एन है ओटी से पता चला (हमारी वेब पृष्ठ अभी भी प्रदर्शित किया जाता है)
iOS 4.3 पर (के रूप में की उम्मीद काम करता है):
- फेसबुक लॉगइन पेज ब्राउज़र का एक ही UIWebView वस्तु में खोला जाता है (हमारे वेब पेज की जगह)

अपेक्षित परिणाम :
- फेसबुक लॉगिन पेज प्रदर्शित किया गया है, और उपयोगकर्ता फेसबुक लॉगिन & पासवर्ड
- आईओएस पर काम करता है 5. + और आईओएस 6. + अगर आईपैड पर सफारी ब्राउज़र में लॉन्च किया गया है। फेसबुक प्रवेश पृष्ठ एक अलग टैब में खोला जाता है (इसके विपरीत में, देखते हैं UIWebView में कोई अलग टैब)

प्रश्न: मैं UIWebView कैसे प्राप्त कर सकते हैं iOS पर OAuth अनुरोध के जवाब में फेसबुक प्रवेश पृष्ठ खोलने के लिए 5 + और iOS 6 +?

अधिक तकनीकी जानकारी:

हम

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

भीतर से अलग NSURLRequest क्षेत्रों लॉग इन करें और हम "सही" और "गलत" व्यवहार के लिए लॉग में कुछ अंतर नोटिस। यहाँ निष्पादन मुझे देखने के प्रवाह कैसे:

सबसे पहले, मैं "अमेरिकन प्लान वेब एप्लिकेशन" लांच बटन दबाएँ OAuth आरंभ करने के लिए, तो कुछ मामलों

iOS 4.3, "सही"
अनुरोध www.facebook.com के लिए जाना/संवाद/oauth? ...
fbwebapp.com
अनुरोध m.facebook.com/login.php के लिए अनुरोध? ....
--here फेसबुक लॉगइन

iOS 5.0, "incorrect1"
अनुरोध www.facebook.com/dialog/oauth के लिए? ... m.facebook को
अनुरोध fbwebapp.com को
अनुरोध प्रकट होता है। com/login.php? ...

तो यह
m.facebook.com/login.php?...with अगले की --a बहुत हो सकता है ... मापदंडों
SQLite त्रुटि
के बाद में - ठीक है अब मैं देखता हूं "क्षमा करें, कुछ गलत हो गया" पी जीई फेसबुक से

iOS 6.0 "incorrect2"
अनुरोध www.facebook.com/dialog/oauth के लिए? ... fbwebapp.com को
अनुरोध (यह एक पहली बार सब पर मैं यह मुठभेड़ है)

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

आप देख सकते हैं कि व्यवहार निश्चित रूप से आईओएस संस्करण पर निर्भर करता है। लेकिन आम मामला यह है कि m.facebook.com/login.php प्राप्त करने के चरण पर त्रुटि होती है .. यूआरएल। लेकिन यह सब हम पहचान सकते हैं।

हम पूरे दिन उस दीवार के खिलाफ समाधानों की तलाश में अपने सिर को टक्कर दे रहे हैं। बुरी।
क्या आप ओएथ के जवाब में UIWebView में खोला गया फेसबुक लॉगिन पृष्ठ प्राप्त करने में हमारी सहायता कर सकते हैं?

उत्तर

0

उपयोगकर्ता को लॉगिन करने के लिए संकेत देने के लिए FBDialog क्लास का उपयोग करें। यह सफल लॉगिन करके एप्लिकेशन के अंदर वेब दृश्य का उपयोग करता है, इसलिए किसी भी उपयोगकर्ता UIWebView के अंदर में लॉग इन किया जाएगा:

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]; 

फिर अपने वर्ग FBDialogDelegate प्रोटोकॉल का पालन करना, और अपने वर्ग के लिए इस समारोह जोड़ें:

-(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]; 
} 

एचटीएच!

+0

, तो आप इस समाधान के बारे में अधिक समझा सकता है? मैं आईओएस में नौसिखिया हूं, लेकिन पहले से ही कुछ फेसबुक एसडीके नमूने की कोशिश की है। देखें या – owlmsj

3

क्या यह था!

यह एक हैक की तरह है, लेकिन आईओएस 6 पर यूआईवेब व्यू पर जेएस फेसबुक एसडीके लॉगिन आखिरकार काम करता है।

यह कैसे किया जा सकता है? यह एक शुद्ध जेएस + फेसबुक जेएस एसडीके + UIWebView प्रतिनिधि हैंडलिंग फ़ंक्शन समाधान है।

जे एस - प्रथम चरण)

एक प्रवेश बटन (फेसबुक के साथ कनेक्ट करने के लिए) इस समारोह उदाहरण कहता है, कि फेस जे एस लॉगिन/OAuth संवाद को गति प्रदान करेगा:

function loginWithFacebookClick(){ 

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

} 

जे एस - दूसरा चरण)

हर बार जब उपयोगकर्ता वेबपृष्ठ लोड करता है (एफबी के बाद) a authResponseChange श्रोता जोड़ें।init()) उपयोगकर्ता के जुड़ा स्थिति को पकड़ने के लिए:

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 प्रतिनिधि कार्यों के साथ आप फेसबुक OAuth प्रतिक्रियाओं

उद्देश्य सी हैंडलर कर सकते हैं - तीसरा कदम)

- (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]; 
    } 
} 

} 

तो, जब ' 'उपयोगकर्ता को अंतिम लोड किए गए पृष्ठ पर रीडायरेक्ट करें, दूसरा चरण फेसबुक लॉगिन संवाद पर उपयोगकर्ता कार्रवाई को संभालने जा रहा है।

अगर मैं इस उत्तर के साथ बहुत तेज़ हो गया, तो कृपया मुझसे पूछो! उम्मीद है कि यह मदद करता है।

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

में फेसबुक को खोलने के लिए मामला किसी में googling है की जरूरत है, यहाँ क्या मेरे लिए काम किया है:

-(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

आपके वेब कार्यान्वयन के आधार पर, एक अतिरिक्त कदम होगा। फेसबुक स्क्रिप्ट वास्तव में window.close() निष्पादित करता है तो window.open() फिर window.close() निष्पादित करता है। मेरे लिए यह समस्याएं पैदा कर रहा था क्योंकि वेब पक्ष पर, इस लॉगिन के पूरा होने के बाद, मेरी खिड़की (यानी वेब व्यू के लिए कि मैं उपयोगकर्ता को लॉग इन करना चाहता हूं) को फेसबुक एसडीके से आने वाले window.close() कॉल प्राप्त हो रहा था। मुझे लगता है कि ऐसा इसलिए है क्योंकि फेसबुक एसडीके उम्मीद करता है कि window.open() एक नई विंडो खोलने के लिए कॉल करें जो इसे बंद कर देगा।

चूंकि हमने window.open() की कार्यक्षमता को ओवरराइड नहीं किया है, इसलिए window.open() पर कॉल करने से कुछ भी नहीं होगा, और फेसबुक एसडीके आपकी विंडो को बंद करने का प्रयास करेगा। इससे सभी प्रकार की समस्याएं पैदा हो सकती हैं, लेकिन मेरे लिए पार्स का उपयोग कर रहा हूं, window.localStorage को null पर सेट किया गया था, इसलिए मुझे सभी प्रकार की त्रुटियां मिल रही थीं।

कुछ इस तरह आप के लिए हो रहा है, तो आपके पास दो विकल्प इसे ठीक करने के लिए है:

  1. आप वेब कोड का नियंत्रण है, तो और एक छोटे से हैक करने के लिए अपने नीचे, window.close=function(){}
  2. में इस फेंक
  3. यदि आपके पास वेब कोड का नियंत्रण नहीं है, तो आप मुख्य वेब व्यू के लिए window.close पर ओवरराइड जोड़ सकते हैं जैसे हमने पॉपअप वेब व्यू के लिए किया था, या window.open फ़ंक्शन को अन्य पॉपअप खोलने के लिए ओवरराइड (जिसे more detail here में वर्णित किया गया है)
0

UIWebView में फेसबुक लॉगिन कैसे करें।

ऑब्जेक्टिव-सी

उपयोग taylorstine's answer। उसने अपना दिन बचाया। धन्यवाद taylorstine

लेकिन मैं स्विफ्ट 3 का उपयोग कर रहा हूं इसलिए मैंने टेलरस्टीन के उत्तर से नीचे कोड को रूपांतरित कर दिया।

स्विफ्ट 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)") 

    } 

} 
संबंधित मुद्दे