简体   繁体   中英

Facebook iOS SDK login native and UIWebView login

For an app I'm working on I need the users to be able to login to Facebook using the native SDK, but there is also a separate part of the app using an FB comments widget in a webview. The problem is after the user logs in using native SDK they are not logged in within the webview comments widget. Is there a way to have the user login using the native iOS SDK and then also log them into Facebook in a UIWebView. I tried using openAccessTokenFromData:completionHandler: in the FBSession class after the user signed in but couldn't get that to work, like below

- (void)didLogin
{
    FBAccessTokenData *data = [FBAccessTokenData createTokenFromString:[FBSession activeSession].accessTokenData.accessToken
                                                       permissions:[FBSession activeSession].accessTokenData.permissions
                                                    expirationDate:[FBSession activeSession].accessTokenData.expirationDate
                                                         loginType:FBSessionLoginTypeWebView
                                                       refreshDate:nil];

    [[FBSession activeSession] closeAndClearTokenInformation];

    FBSession *session = [[FBSession alloc] init];

    [session openFromAccessTokenData:data
               completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
               }];
}    

I used following code to open Facebook iOs SDK login in Webview in my native app and its works fine for me.

-(void)openFacebookAuthentication
{
    NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];

    FBSession *session = [[FBSession alloc] initWithPermissions:permission];

    [FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];

    [[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {

        switch (status) {
            case FBSessionStateOpen:
                [self getMyData];
                break;
            case FBSessionStateClosedLoginFailed: {
                // prefer to keep decls near to their use
                // unpack the error code and reason in order to compute cancel bool
                NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
                NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
                BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);


                if(error.code == 2 && ![errorReason isEqualToString:@"com.facebook.sdk:UserLoginCancelled"]) {
                    UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:kFBAlertTitle
                                                                           message:kFBAuthenticationErrorMessage
                                                                           delegate:nil
                                                                           cancelButtonTitle:kOk
                                                                           otherButtonTitles:nil];
                    [errorMessage performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];
                    errorMessage = nil;
                    }
                }
                break;
                // presently extension, log-out and invalidation are being implemented in the Facebook class
            default:
                break; // so we do nothing in response to those state transitions
        }
    }];
    permission = nil;
}

Create facebook Appid Facebook Appid creating link Creating time follow facebook guide lines you must give bundile identfier in register time 在** plist **中提供Facebook appid信息,如吹像

Then Use this Code

@interface LoginViewController : UIViewController<UIWebViewDelegate>
@property(nonatomic,retain)UIWebView *webview;
@property (nonatomic, retain) NSString *accessToken;
@property(nonatomic,retain)UIActivityIndicatorView  *FbActive;
@end
@interface LoginViewController ()

@end

@implementation LoginViewController
@synthesize accessToken,webview,FbActive;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

   //Removeing the UIWebview Cookies 
    NSHTTPCookie *cookie;
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (cookie in [storage cookies]) {
        [storage deleteCookie:cookie];
    }
    [[NSUserDefaults standardUserDefaults] synchronize];


}
-(IBAction)fbLoginPage:(UIButton *)sender1
{


    NSString   *facebookClientID =facebookAppId;
    NSString   *redirectUri = @"http://www.facebook.com/connect/login_success.html";
    NSString  *extended_permissions=@"user_photos,user_videos,publish_stream,offline_access,user_checkins,friends_checkins,email";

    NSString *url_string = [NSString stringWithFormat:@"https://graph.facebook.com/oauth/authorize?client_id=%@&redirect_uri=%@&scope=%@&type=user_agent&display=touch", facebookClientID, redirectUri, extended_permissions];
    NSURL *url = [NSURL URLWithString:url_string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    CGRect webFrame =[self.view frame];
    webFrame.origin.y = 0;
    UIWebView *aWebView = [[UIWebView alloc] initWithFrame:webFrame];
    [aWebView setDelegate:self];
    self.webview = aWebView;
    self.FbActive = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    self.FbActive.color=[UIColor darkGrayColor];
    self.FbActive.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
    [self.FbActive startAnimating];

    [webview loadRequest:request];
    [self.webview addSubview:self.FbActive];
    [self.view addSubview:webview];


}

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

    /**
     * Since there's some server side redirecting involved, this method/function will be called several times
     * we're only interested when we see a url like:  http://www.facebook.com/connect/login_success.html#access_token=..........
     */

    //get the url string
     [self.FbActive stopAnimating];
    NSString *url_string = [((_webView.request).URL) absoluteString];

    //looking for "access_token="
    NSRange access_token_range = [url_string rangeOfString:@"access_token="];

    //looking for "error_reason=user_denied"
    NSRange cancel_range = [url_string rangeOfString:@"error_reason=user_denied"];

    //it exists?  coolio, we have a token, now let's parse it out....
    if (access_token_range.length > 0) {

        //we want everything after the 'access_token=' thus the position where it starts + it's length
        int from_index = access_token_range.location + access_token_range.length;
        NSString *access_token = [url_string substringFromIndex:from_index];

        //finally we have to url decode the access token
        access_token = [access_token stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        //remove everything '&' (inclusive) onward...
        NSRange period_range = [access_token rangeOfString:@"&"];

        //move beyond the .
        access_token = [access_token substringToIndex:period_range.location];

        //store our request token....
        self.accessToken = access_token;

        //remove our window
//      UIWindow* window = [UIApplication sharedApplication].keyWindow;
//      if (!window) {
//          window = [[UIApplication sharedApplication].windows objectAtIndex:0];
//      }

        [self.webview removeFromSuperview];
         self.webview=nil;



        //tell our callback function that we're done logging in :)
        //      if ( (callbackObject != nil) && (callbackSelector != nil) ) {
        //          [callbackObject performSelector:callbackSelector];
        //      }

        //the user pressed cancel

    }
    else if (cancel_range.length > 0)
    {
        //remove our window
//      UIWindow* window = [UIApplication sharedApplication].keyWindow;
//      if (!window) {
//          window = [[UIApplication sharedApplication].windows objectAtIndex:0];
//      }

        [self.webview removeFromSuperview];
        self.webview=nil;

        //tell our callback function that we're done logging in :)
        //      if ( (callbackObject != nil) && (callbackSelector != nil) ) {
        //          [callbackObject performSelector:callbackSelector];
        //      }

    }
    [self getuserdetailes];

}

-(void)getuserdetailes
{
    NSString *action=@"me";

    NSString *url_string = [NSString stringWithFormat:@"https://graph.facebook.com/%@?", action];

    //tack on any get vars we have...

    NSDictionary *get_vars=nil;

    if ( (get_vars != nil) && ([get_vars count] > 0) ) {

        NSEnumerator *enumerator = [get_vars keyEnumerator];
        NSString *key;
        NSString *value;
        while ((key = (NSString *)[enumerator nextObject])) {

            value = (NSString *)[get_vars objectForKey:key];
            url_string = [NSString stringWithFormat:@"%@%@=%@&", url_string, key, value];

        }//end while
    }//end if

    if (accessToken != nil)
    {

        //now that any variables have been appended, let's attach the access token....
        url_string = [NSString stringWithFormat:@"%@access_token=%@", url_string, self.accessToken];
        url_string = [url_string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSLog(@"%@",url_string);
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url_string]];

        NSError *err;
        NSURLResponse *resp;
        NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&err];
        NSString *stringResponse = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
        NSLog(@"%@",stringResponse);
        NSError* error;
        NSDictionary *FBResResjson = [NSJSONSerialization
                                      JSONObjectWithData:response//1
                                      options:kNilOptions
                                      error:&error];
            NSLog(@"%@",FBResResjson);


    }
}

thank to Divya Bhalodiya answered. this is the swift 3 version with Facebook SDK 4.x. If the code has any problem, feel free to edit & comment. Hope this will help.

func verifyFromWebView() {
  let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
  fbLoginManager.loginBehavior = FBSDKLoginBehavior.web
  fbLoginManager.logIn(withReadPermissions: ["email"], from: self) { (result, error) in
    if error != nil {
        print(error!.localizedDescription)
        self.dismiss(animated: true, completion: nil)
    }else if (result?.isCancelled)!{
        print("Cancelled")
        self.dismiss(animated: true, completion: nil)
    }else{

        if let fbLoginResult = result {
            if fbLoginResult.grantedPermissions != nil && fbLoginResult.grantedPermissions.contains("email"){

                self.getFBData()

            }
        }
     }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM