本文介紹在iOS上集成Google和Apple三方登錄的開發(fā)指南。
Google登錄
- 創(chuàng)建項目
-
打開Google后臺,單擊左上角My Project,再在彈出框中單擊創(chuàng)建項目。
- 接下來申請配置項目參數(shù),在集成開發(fā)界面中單擊Create an OAuth clientID按鈕。
- 選擇剛才創(chuàng)建的項目,選擇平臺iOS,輸入項目
BundleID
,成功之后會提示下載一個plist
文件,里面包含了配置參數(shù)。
-
- Xcode工程配置
在xcode工程的
info.plist
文件中配置url scheme
,URL Schemes
參數(shù)填Google生成plist
文件中的REVERSED_CLIENT_ID
。
代碼示例
#import <ALBBOpenAccountSSO/ALBBOpenAccountSSOService.h>
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>
//Google生成plist文件中的CLIENT_ID
static NSString * const IMSAuthPlatformGoogleAppKey = @"xxxx.apps.googleusercontent.com";
@implementation GoogleLoginDemo
- (instancetype)init {
self = [super init];
if (self) {
//登錄成功通知
[IMSNotification addObserverForName:ALBBOpenAccountNotificationUserLoggedIn object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
if (note.object != nil && ([note.object isEqualToString:ALBBOpenAccountNotificationTrigerByREG] || [note.object isEqualToString:ALBBOpenAccountNotificationTrigerByLogin])) {
}
}];
}
return self;
}
//拉起Google授權(quán)登錄
- (void)thirdAuthorizationLogin {
id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
//初始化
[ssoService setPlatform:OAAuthPlatformType_Google
appKey:IMSAuthPlatformGoogleAppKey
appSecret:nil
redirectURL:nil];
//三方賬號授權(quán)登錄
[ssoService oauthWithPlatForm:OAAuthPlatformType_Google
presentingVC:self
delegate:self];
}
#pragma mark - SSODelegate
- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
if (error && error.code != -5) {
//處理授權(quán)登錄錯誤
}
}
@end
在AppDelegate里需要處理系統(tǒng)回調(diào),代碼示例如下所示- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *sourceApplication = [options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey];
id annotation = [options objectForKey:UIApplicationOpenURLOptionsAnnotationKey];
return [ALBBService(ALBBOpenAccountSSOService) handleOpenUrl:url application:app
sourceApplication:sourceApplication annotation:annotation];
}
Apple登錄
項目配置
- 在蘋果開發(fā)者網(wǎng)站,開通sign in with Apple。
- 在Xcode中添加sign in with Apple。
選中target,在Signing & Capabilities中點擊Capability選擇sign in with Apple。
代碼示例
#import <ALBBOpenAccountSSO/ALBBOpenAccountSSOService.h>
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>
#import <IMSApiClient/IMSConfiguration.h>
#if __has_include(<AuthenticationServices/AuthenticationServices.h>)
#import "AuthenticationServices/AuthenticationServices.h"
#endif
@implementation AppleLoginDemo
- (instancetype)init {
self = [super init];
if (self) {
//登錄成功通知
[IMSNotification addObserverForName:ALBBOpenAccountNotificationUserLoggedIn object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
if (note.object != nil && ([note.object isEqualToString:ALBBOpenAccountNotificationTrigerByREG] || [note.object isEqualToString:ALBBOpenAccountNotificationTrigerByLogin])) {
}
}];
}
return self;
}
//拉起Apple授權(quán)登錄
- (void)handleAplleAuthrization {
if (@available(iOS 13.0, *)) {
// A mechanism for generating requests to authenticate users based on their Apple ID.
// 基于用戶的Apple ID授權(quán)用戶,生成用戶授權(quán)請求的一種機制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// Creates a new Apple ID authorization request.
// 創(chuàng)建新的AppleID 授權(quán)請求
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
// The contact information to be requested from the user during authentication.
// 在用戶授權(quán)期間請求的聯(lián)系信息
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
// A controller that manages authorization requests created by a provider.
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請求 管理授權(quán)請求的控制器
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
// A delegate that the authorization controller informs about the success or failure of an authorization attempt.
// 設(shè)置授權(quán)控制器通知授權(quán)請求的成功與失敗的代理
controller.delegate = self;
// A delegate that provides a display context in which the system can present an authorization interface to the user.
// 設(shè)置提供 展示上下文的代理,在這個上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
controller.presentationContextProvider = self;
// starts the authorization flows named during controller initialization.
// 在控制器初始化期間啟動授權(quán)流
[controller performRequests];
}
}
#pragma mark - ASAuthorizationControllerDelegate
#if __has_include(<AuthenticationServices/AuthenticationServices.h>)
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)){
NSMutableString *mStr = [NSMutableString string];
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// 用戶登錄使用ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
NSString *familyName = appleIDCredential.fullName.familyName;
NSString *givenName = appleIDCredential.fullName.givenName;
NSString *email = appleIDCredential.email;
NSMutableString* nick = [[NSMutableString alloc]initWithCapacity:3];
if (givenName != nil) {
[nick appendString:givenName];
[nick appendString:@" "];
}
if (familyName != nil) {
[nick appendString:familyName];
}
NSDictionary* userInfo = @{@"nick":nick.length > 0? nick : user, @"email":@""};
NSString* identityToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding];
id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
//蘋果賬號登錄
[ssoService signInWithApple:self
clientId:[[NSBundle mainBundle] bundleIdentifier]
identityToken:identityToken
appKey:[IMSConfiguration sharedInstance].appKey
openId:user
userInfo:userInfo
delegate:self];
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
// 用戶登錄使用現(xiàn)有的密碼憑證
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對象的用戶標(biāo)識 用戶的唯一標(biāo)識
NSString *user = passwordCredential.user;
// 密碼憑證對象的密碼
NSString *password = passwordCredential.password;
[mStr appendString:user?:@""];
[mStr appendString:password?:@""];
[mStr appendString:@"\n"];
NSLog(@"mStr:%@", mStr);
} else {
NSLog(@"授權(quán)信息均不符");
mStr = [@"授權(quán)信息均不符" mutableCopy];
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)){
NSLog(@"%s", __FUNCTION__);
NSLog(@"錯誤信息:%@", error);
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"用戶取消了授權(quán)請求";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"授權(quán)請求失敗";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"授權(quán)請求響應(yīng)無效";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"未能處理授權(quán)請求";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"授權(quán)請求失敗未知原因";
break;
}
if (errorMsg) {
return;
}
NSLog(@"controller requests:%@", controller.authorizationRequests);
}
#pragma mark - ASAuthorizationControllerPresentationContextProviding
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
NSLog(@"調(diào)用展示window方法:%s", __FUNCTION__);
// 返回window
return self.view.window;
}
#endif
#pragma mark - SSODelegate
- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
if (error && error.code != -5) {
//處理授權(quán)登錄錯誤
}
}
@end
在AppDelegate里需要處理系統(tǒng)回調(diào),代碼示例如下所示- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *sourceApplication = [options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey];
id annotation = [options objectForKey:UIApplicationOpenURLOptionsAnnotationKey];
return [ALBBService(ALBBOpenAccountSSOService) handleOpenUrl:url application:app
sourceApplication:sourceApplication annotation:annotation];
}