ios5中的Facebook SSO [英] Facebook SSO in ios5

查看:146
本文介绍了ios5中的Facebook SSO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的iOS应用程序中集成了Facebook的问题。当我启动我的应用程序,它重定向到Facebook应用程序,这是很好的。但是,auth对话框只是从屏幕上消失(就像一个被解雇的模态视图控制器),代理方法不会触发,而是留在Facebook应用程序中,而不是重定向到我的应用程序。我显然没有成功初始化会话。我按照iOS教程中的步骤进行操作,但我必须在某处出错。我看到的大多数问题都是关于错误或试图从auth对话框中获得不同的行为。如果这是一个骗子,请指示我这个相同的问题,因为我在这里打墙。正如教程中所说的那样,我已经设置了我的.plist。我使用我从iTunes连接抓取的我的应用程序的包标识符。我的常数kAppID是我从Facebook开发人员应用界面获得的AppID。阅读了FB静态库的头文件和实现文件,以及FB的文档和教程,在我看来,如果我想做的是重定向到FB应用程序,登录并重定向到我自己的应用程序,这些步骤加上下面的代码应该是足够的。



在AppDelegate.m中:

   - (BOOL) (UIApplication *)应用程序didFinishLaunchingWithOptions :( NSDictionary *)launchOptions 
{
kAppID = @(这是我的应用程序ID的位置);
//在应用程序启动后覆盖自定义点。
facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:self];
[facebook setSessionDelegate:self];
返回YES;
}

在ViewController.m中,我抓住了同一个Facebook实例的引用,然后调用以下内容:

   - (void)loginToFacebook:(id)sender {
if([defaults objectForKey :@FBAccessTokenKey]&&&';默认对象ForKey:@FBExpirationDateKey]){
facebook.accessToken = [defaults objectForKey:@FBAccessTokenKey];
facebook.expirationDate = [defaults objectForKey:@FBExpirationDateKey];
}
if(![facebook isSessionValid]){
[facebook authorize:nil];
}
}

有没有一些我不知道的?或者也许我错过了关键的一步?
提前感谢任何协助。



哦,btw,Xcode 4.3.1,ios5SDK,iPhone 4S,ARC。



.plist的SS。



AppDelegate.h: / p>

  #import< UIKit / UIKit.h> 
#importFacebook.h
#importFBConnect.h

@interface AppDelegate:UIResponder< UIApplicationDelegate> {
Facebook * facebook;
NSUserDefaults * defaults;
NSString * kAppID;
}

@property(强,非原子)UIWindow *窗口;
@property(强,非原子)Facebook * facebook;
@property(strong,nonatomic)id delegate;

@end

AppDelegate.m:

$ b $


$ b $ $ $
@synthesize window = _window;
@synthesize Facebook;
@synthesize delegate;

- (BOOL)应用程序:(UIApplication *)应用程序didFinishLaunchingWithOptions :( NSDictionary *)launchOptions
{
ViewController * viewController = [[ViewController alloc] init];
kAppID = @385380598149062;
facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:viewController];

返回YES;
}

- (void)showSession {
NSLog(@FB Session:%@,[NSNumber numberWithBool:[facebook isSessionValid]]);
}

- (void)applicationWillResignActive:(UIApplication *)应用程序
{
//当应用程序即将从活动状态移动到非活动状态时发送。某些类型的暂时中断(如来电或短信)或当用户退出应用程序并开始转换到背景状态时,可能会发生这种情况。
//使用此方法暂停正在进行的任务,禁用定时器,并降低OpenGL ES帧速率。游戏应该使用这种方法暂停游戏。
}

- (void)applicationDidEnterBackground:(UIApplication *)应用程序
{
//使用此方法释放共享资源,保存用户数据,使定时器无效,并存储足够的应用程序状态信息以将应用程序恢复到当前状态,以备稍后终止。
//如果您的应用程序支持后台执行,则调用此方法而不是applicationWillTerminate:当用户退出时。
}

- (void)applicationWillEnterForeground:(UIApplication *)应用程序
{
//被调用为从后台转换到非活动状态的一部分;在这里,您可以撤消进入后台的许多更改。
}

- (void)applicationDidBecomeActive :( UIApplication *)应用程序
{
//在应用程序中重新启动任何已暂停(或尚未启动)的任务没有活动如果应用程序以前在后台,请选择刷新用户界面。
}

- (void)applicationWillTerminate :( UIApplication *)应用程序
{
//当应用程序即将终止时调用。酌情保存数据。另请参见applicationDidEnterBackground :.
}

@end

如你所见,不这些方法很多。委托类是ViewController。所有我真正在AppDelegate中做的都是初始化Facebook实例。在这一点上,Herre的整个ViewController.m(减去一些非facebook相关的东西):

  #importViewController.h 

@interface ViewController()

@end

@implementation ViewController

@synthesize contacts,contactArray;

- (void)viewDidLoad
{
[super viewDidLoad];
defaults = [NSUserDefaults standardUserDefaults];
AppDelegate * delegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
facebook = delegate.facebook;
[facebook setSessionDelegate:self];
[self loginToFacebook:nil];
eventsArray = [[NSMutableArray alloc] initWithObjects:@Event one,@Event two,nil];
}

- (void)viewDidUnload
{
[super viewDidUnload];
//发布主视图的任何保留的子视图。


- (BOOL)shouldAutorotateToInterfaceOrientation :( UIInterfaceOrientation)interfaceOrientation
{
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
return(interfaceOrientation = UIInterfaceOrientationPortrait);
} else {
return NO;
}
}

- (void)loginToFacebook:(id)sender {
if([defaults objectForKey:@FBAccessTokenKey]&& objectForKey:@FBExpirationDateKey]){
facebook.accessToken = [defaults objectForKey:@FBAccessTokenKey];
facebook.expirationDate = [defaults objectForKey:@FBExpirationDateKey];
NSLog(@accessToken:%@ \ expiry:%@,facebook.accessToken,facebook.expirationDate);
}
if(![facebook isSessionValid]){
[facebook authorize:nil];
}
}

- (BOOL)应用程序:(UIApplication *)应用程序handleOpenURL:(NSURL *)url {
NSLog(@handle open url ;
return [facebook handleOpenURL:url];


- (BOOL)应用程序:(UIApplication *)应用程序openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication注释:(id)注释{
return [facebook handleOpenURL:url];
}

- (void)request:(FBRequest *)请求didLoad:(id)result {
//好,所以它是一个字符与一个元素(key =数据),它是一个字典数组,每个都有name和id键
fbContacts = [(NSDictionary *)result objectForKey:@data];
NSLog(@请求加载); (int i = 0; i< [fbContacts count]; i ++){
NSDictionary * friend = [fbContacts objectAtIndex:i];

long long fbid = [[friend objectForKey:@id] longLongValue];
NSString * name = [friend objectForKey:@name];
NSLog(@id:%lld - Name:%@,fbid,name);
}
}

- (void)fbDidLogin {
NSLog(@FB确实登录);
[defaults setObject:[facebook accessToken] forKey:@FBAccessTokenKey];
[defaults setObject:[facebook expirationDate] forKey:@FBExpirationDateKey];
[默认同步];
[facebook requestWithGraphPath:@me / friendsandDelegate:self];

}

- (void)fbDidNotLogin:(BOOL)已取消{
NSLog(@FB登录取消);
}

/ **
*扩展访问令牌后调用。如果您的应用程序对以前的访问令牌有任何
*引用(例如,如果您的应用程序
*将以前的访问令牌存储在持久存储器中),您的应用程序
*将覆盖旧的访问权限在这个方法中使用新的令牌。
*有关详细信息,请参阅extendAccessToken。
* /
- (void)fbDidExtendToken:(NSString *)accessToken
expiresAt :( NSDate *)expiresAt {
NSLog(@FB extended token);
}

/ **
*用户注销时调用。
* /
- (void)fbDidLogout {
NSLog(@FB注销);
[defaults removeObjectForKey:@FBAccessTokenKey];
[defaults removeObjectForKey:@FBExpirationDateKey];
[默认同步];
}

/ **
*当当前会话已过期时调用。这可能发生在以下情况:
* - 访问令牌过期
* - 应用程序已禁用
* - 用户撤销了应用程序的权限
* - 用户更改了他或她密码
* /
- (void)fbSessionInvalidated {
NSLog(@FB session invalidated);
}
@end


解决方案

.plist看起来不错,也许你只是忘了openurl处理程序?

   - (BOOL)应用程序:(UIApplication *)application handleOpenURL: (NSURL *)url {
return [self.facebook handleOpenURL:url];


- (BOOL)应用程序:(UIApplication *)应用程序openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication注释:(id)注释{
return [self.facebook handleOpenURL:url];
}

UPD:


  1. 作为一个实验,你可以尝试这个(从Hackbook的例子):

      //现在检查URL方案fb [app_id]:// authorize是否在.plist中,并且可以
    //打开,做一个简单的检查,没有本地的应用程序id因子在这里
    NSString * url = [NSString stringWithFormat:@fb%@:// authorize,kAppId];
    BOOL bSchemeInPlist = NO; //找出sceme是否在plist文件中。
    NSArray * aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@CFBundleURLTypes];
    if([aBundleURLTypes isKindOfClass:[NSArray class]]&&
    ([aBundleURLTypes count]> 0)){
    NSDictionary * aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0];
    if([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]){
    NSArray * aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@CFBundleURLSchemes];
    if([aBundleURLSchemes isKindOfClass:[NSArray class]]&&
    ([aBundleURLSchemes count]> 0)){
    NSString * scheme = [aBundleURLSchemes objectAtIndex:0];
    if([scheme isKindOfClass:[NSString class]]&&
    [url hasPrefix:scheme]){
    bSchemeInPlist = YES;
    }
    }
    }
    }
    //检查授权回调是否有效
    BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString :url]];
    如果(!bSchemeInPlist ||!bCanOpenUrl){
    UIAlertView * alertView = [[UIAlertView alloc]
    initWithTitle:@安装程序错误
    消息:@无效或缺少URL在您的.plist中设置一个有效的URL方案之前,您无法运行该应用程序。
    delegate:self
    cancelButtonTitle:@OK
    otherButtonTitles:nil,
    nil];
    [alertView show];
    [alertView release];
    }

    在这一步我们将知道,URL方案是正确的


  2. 尝试更改
    [facebook authorize:nil];
    with
    [facebook authorize:[[NSArray alloc] initWithObjects:@read_friendlists,nil]];
    所以也许SSO要求至少指定一个权限。



I'm having issues with integrating facebook into my iOS app. When I launch my app, it redirects to the facebook app, which is good. But the auth dialog just vanishes from the screen (like a dismissed modal view controller), the delegate methods aren't firing, and I'm left in the facebook app instead of being redirected back to my app. I'm apparently not successfully initializing a session. I followed the steps in the iOS tutorial but I must have gone wrong somewhere. Most of the questions I've seen have been about errors or trying to get different behavior out of the auth dialog. If this is a dupe, please direct me to the identical question because I'm hitting a wall here. I have set up my .plist just as it says to in the tutorial. I used the bundle identifier for my app that I grabbed from iTunes connect. My constant kAppID is the AppID that I got from the Facebook Developer app interface. Having read through the headers and implementation files of the FB static lib, as well as FB's docs and tutorial, it seems to me that if all I want to do is redirect to FB app, sign in, and be redirected back to my own app, that these steps plus the code below should be sufficient.

In AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    kAppID = @"(this is where my app ID is)";
    // Override point for customization after application launch.
    facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:self];
    [facebook setSessionDelegate:self];
    return YES;
}

And in ViewController.m I grab a reference to that same instance of Facebook, and then call the following:

- (void)loginToFacebook:(id)sender {
    if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
    }
    if (![facebook isSessionValid]) {
        [facebook authorize:nil];
    }
}

Is there some gotcha that I'm not aware of? Or maybe I'm missing a critical step? Thanks in advance for any assistance.

Oh, btw, Xcode 4.3.1, ios5SDK, iPhone 4S, ARC.

SS of .plist.

AppDelegate.h:

#import <UIKit/UIKit.h>
#import "Facebook.h"
#import "FBConnect.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    Facebook *facebook;
    NSUserDefaults *defaults;
    NSString *kAppID;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) Facebook *facebook;
@property (strong, nonatomic) id delegate;

@end

AppDelegate.m:

#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize facebook;
@synthesize delegate;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ViewController *viewController = [[ViewController alloc] init];
    kAppID = @"385380598149062";
    facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:viewController];

    return YES;
}

- (void)showSession {
    NSLog(@"FB Session: %@", [NSNumber numberWithBool:[facebook isSessionValid]]);
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

As you can see, not much happens in these methods. The delegate class is the ViewController. All I really do in the AppDelegate is init the Facebook instance. On that note, herre's the whole ViewController.m (minus some non-facebook related stuff):

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize contacts, contactArray;

- (void)viewDidLoad
{
    [super viewDidLoad];
    defaults = [NSUserDefaults standardUserDefaults];
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    facebook = delegate.facebook;
    [facebook setSessionDelegate:self];
    [self loginToFacebook:nil];
    eventsArray = [[NSMutableArray alloc] initWithObjects:@"Event one", @"Event two", nil];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation = UIInterfaceOrientationPortrait);
    } else {
        return NO;
    }
}

- (void)loginToFacebook:(id)sender {
    if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
        NSLog(@"accessToken:%@\n expiry:%@", facebook.accessToken, facebook.expirationDate);
    }
    if (![facebook isSessionValid]) {
        [facebook authorize:nil];
    }
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    NSLog(@"handle open url");
    return [facebook handleOpenURL:url];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [facebook handleOpenURL:url];
}

- (void)request:(FBRequest *)request didLoad:(id)result {
    //ok so it's a dictionary with one element (key="data"), which is an array of dictionaries, each with "name" and "id" keys
    fbContacts = [(NSDictionary *)result objectForKey:@"data"];
    NSLog(@"Request did load");
    for (int i=0; i<[fbContacts count]; i++) {
        NSDictionary *friend = [fbContacts objectAtIndex:i];
        long long fbid = [[friend objectForKey:@"id"]longLongValue];
        NSString *name = [friend objectForKey:@"name"];
        NSLog(@"id: %lld - Name: %@", fbid, name);
    }
}

- (void)fbDidLogin {
    NSLog(@"FB did log in");
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];
    [facebook requestWithGraphPath:@"me/friends" andDelegate:self];

}

- (void)fbDidNotLogin:(BOOL)cancelled {
    NSLog(@"FB login cancelled");
}

/**
 * Called after the access token was extended. If your application has any
 * references to the previous access token (for example, if your application
 * stores the previous access token in persistent storage), your application
 * should overwrite the old access token with the new one in this method.
 * See extendAccessToken for more details.
 */
- (void)fbDidExtendToken:(NSString*)accessToken
               expiresAt:(NSDate*)expiresAt {
    NSLog(@"FB extended token");
}

/**
 * Called when the user logged out.
 */
- (void)fbDidLogout {
    NSLog(@"FB logged out");
    [defaults removeObjectForKey:@"FBAccessTokenKey"];
    [defaults removeObjectForKey:@"FBExpirationDateKey"];
    [defaults synchronize];
}

/**
 * Called when the current session has expired. This might happen when:
 *  - the access token expired
 *  - the app has been disabled
 *  - the user revoked the app's permissions
 *  - the user changed his or her password
 */
- (void)fbSessionInvalidated {
    NSLog(@"FB session invalidated");
}
@end

解决方案

.plist looks great, maybe you just forgot about openurl handler?

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    return [self.facebook handleOpenURL:url];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [self.facebook handleOpenURL:url];
}

UPD:

  1. Just as an experiment, could you try this (from Hackbook example):

    // Now check that the URL scheme fb[app_id]://authorize is in the .plist and can
    // be opened, doing a simple check without local app id factored in here
    NSString *url = [NSString stringWithFormat:@"fb%@://authorize",kAppId];
    BOOL bSchemeInPlist = NO; // find out if the sceme is in the plist file.
    NSArray* aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
    if ([aBundleURLTypes isKindOfClass:[NSArray class]] &&
        ([aBundleURLTypes count] > 0)) {
        NSDictionary* aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0];
        if ([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]) {
            NSArray* aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"];
            if ([aBundleURLSchemes isKindOfClass:[NSArray class]] &&
                ([aBundleURLSchemes count] > 0)) {
                NSString *scheme = [aBundleURLSchemes objectAtIndex:0];
                if ([scheme isKindOfClass:[NSString class]] &&
                    [url hasPrefix:scheme]) {
                    bSchemeInPlist = YES;
                }
            }
        }
    }
    // Check if the authorization callback will work
    BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]];
    if (!bSchemeInPlist || !bCanOpenUrl) {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Setup Error"
                                  message:@"Invalid or missing URL scheme. You cannot run the app until you set up a valid URL scheme in your .plist."
                                  delegate:self
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil,
                                  nil];
        [alertView show];
        [alertView release];
    }
    

    At this step we will know, that it is all right with the URL scheme.

  2. Try to change [facebook authorize:nil]; with [facebook authorize:[[NSArray alloc] initWithObjects:@"read_friendlists", nil]]; so maybe SSO requires at least one permission to be specified.

这篇关于ios5中的Facebook SSO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆