- 蘋果授權登錄配置
1.Identifiers 勾選 Sign In with Apple
2.配置key
3.
4.key 與 Certificates 關聯
5
6. 更新Profiles的開發配置文件並下載
7. Xcode 開啓 Sign In with Apple
- 蘋果授權登錄代碼封裝
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, AppleLoginType) {
AppleLoginTypeUnknown = 0,
AppleLoginTypeSuccessful,
AppleLoginTypeUserSuccessful,
AppleLoginTypeFailure
};
@interface AppleLogin : UIView
/// Apple登錄
/// @param user 選填,已存user可以直接快速驗證,沒有傳nil ,斷網可驗證。
/// @param view <#view description#>
/// @param rect <#rect description#>
/// @param block <#block description#>
+(instancetype)appLogoinFromUser:(NSString *)user view:(UIView *)view rect:(CGRect)rect block:(void(^)(NSInteger state,NSString *msg,id data))block;
@end
NS_ASSUME_NONNULL_END
#import "AppleLogin.h"
#import <AuthenticationServices/AuthenticationServices.h>
typedef void(^AppleLoginBlock)(NSInteger state,NSString *msg,id data);
@interface AppleLogin ()
<
ASAuthorizationControllerDelegate
,ASAuthorizationControllerPresentationContextProviding
>
@property(nonatomic,strong)NSString *userId;
@property(nonatomic,strong)UIView *view;
@property(nonatomic)CGRect rect;
@property(nonatomic,copy)AppleLoginBlock appleLoginBlock;
@end
@implementation AppleLogin
+(instancetype)appLogoinFromView:(UIView *)superView rect:(CGRect)rect block:(void(^)(NSInteger state,NSString *msg,id data))block
{
AppleLogin * appleLogin = [self appLogoinFromView:superView rect:rect];
appleLogin.appleLoginBlock = block;
return appleLogin;
}
+(instancetype)appLogoinFromUser:(NSString *)user view:(UIView *)view rect:(CGRect)rect block:(void(^)(NSInteger state,NSString *msg,id data))block
{
AppleLogin * appleLogin = [self appLogoinFromView:view rect:rect];
appleLogin.userId = user;
appleLogin.appleLoginBlock = block;
return appleLogin;
}
+(instancetype)appLogoinFromView:(UIView *)superView rect:(CGRect)rect
{
AppleLogin * appleLogin = [[AppleLogin alloc]initWithFrame:rect];
appleLogin.view = superView;
appleLogin.rect = rect;
[appleLogin initUI];
return appleLogin;
}
- (void)initUI
{
if (@available(iOS 13.0, *))
{
ASAuthorizationAppleIDButton *button = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeSignIn style:ASAuthorizationAppleIDButtonStyleBlack];
button.frame = CGRectMake(0, 0, self.rect.size.width, self.rect.size.height);
button.layer.masksToBounds = YES;
button.layer.cornerRadius = self.frame.size.width/2;
[button addTarget:self action:@selector(signInWithApple) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
[self.view addSubview:self];
}
}
#pragma mark ————————————— 登錄按鈕點擊事件 —————————————
- (void)signInWithApple API_AVAILABLE(ios(13.0))
{
if (@available(iOS 13.0, *))
{
NSLog(@"Apple Login Click");
//基於用戶的Apple ID授權用戶,生成用戶授權請求的一種機制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
if (_userId.length == 0)
{
NSLog(@"授權請求AppleID");
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
[request setRequestedScopes:@[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]];
//由ASAuthorizationAppleIDProvider創建的授權請求 管理授權請求的控制器
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
//設置授權控制器通知授權請求的成功與失敗的代理
controller.delegate = self;
//設置提供 展示上下文的代理,在這個上下文中 系統可以展示授權界面給用戶
controller.presentationContextProvider = self;
//在控制器初始化期間啓動授權流
[controller performRequests];
}
else
{
// NSLog(@"快速登錄使用授權登錄返回的 user ");
//快速登錄
[appleIDProvider getCredentialStateForUserID:_userId completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
if (credentialState == ASAuthorizationAppleIDProviderCredentialAuthorized)
{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeUserSuccessful,@"ok",dic);
}
}
else
{ NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:error.description forKey:@"errorMsg"];
[dic setValue:[NSNumber numberWithInteger:error.code] forKey:@"code"];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeFailure,error.description,dic);
}
}
}];
}
}
else
{
}
}
#pragma mark ————————————— 成功回調 —————————————
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0))
{
// NSLog(@"授權完成:::%@", authorization.credential);
// NSLog(@"%s", __FUNCTION__);
// NSLog(@"%@", controller);
// NSLog(@"%@", authorization);
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 *nickname = appleIDCredential.fullName.nickname;
NSString *email = appleIDCredential.email;
NSString *state = appleIDCredential.state;
NSData *identityToken = appleIDCredential.identityToken;
NSData *authorizationCode = appleIDCredential.authorizationCode;
ASUserDetectionStatus realUserStatus = appleIDCredential.realUserStatus;
// 服務器驗證需要使用的參數
NSString *identityTokenStr = [[NSString alloc] initWithData:identityToken encoding:NSUTF8StringEncoding];
NSString *authorizationCodeStr = [[NSString alloc] initWithData:authorizationCode encoding:NSUTF8StringEncoding];
// NSLog(@"%@\n\n%@", identityTokenStr, authorizationCodeStr);
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:state forKey:@"state"];
[dic setValue:user forKey:@"user"];
[dic setValue:email forKey:@"email"];
[dic setValue:familyName forKey:@"familyName"];
[dic setValue:givenName forKey:@"givenName"];
[dic setValue:nickname forKey:@"nickname"];
// [dic setValue:appleIDCredential forKey:@"appleIDCredential"];
[dic setValue:authorizationCodeStr forKey:@"authorizationCode"];
[dic setValue:identityTokenStr forKey:@"identityToken"];
// [dic setValue:@(realUserStatus) forKey:@"realUserStatus"];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeSuccessful, @"ok",dic);
}
// 需要使用鑰匙串的方式保存用戶的唯一信息 Keychain
}
else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]])
{
// 這個獲取的是iCloud記錄的賬號密碼,需要輸入框支持iOS 12 記錄賬號密碼的新特性,如果不支持,可以忽略
// Sign in using an existing iCloud Keychain credential.
// 用戶登錄使用現有的密碼憑證
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對象的用戶標識 用戶的唯一標識
NSString *user = passwordCredential.user;
// 密碼憑證對象的密碼
NSString *password = passwordCredential.password;
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:user forKey:@"user"];
[dic setValue:password forKey:@"password"];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeSuccessful, @"ok",dic);
}
}
else
{
// NSLog(@"授權信息均不符");
NSString *errorMsg = @"授權信息不符";
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:errorMsg forKey:@"errorMsg"];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeFailure,errorMsg,dic);
}
}
}
#pragma mark ————————————— 失敗回調 —————————————
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0))
{
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"用戶取消了授權請求";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"授權請求失敗";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"授權請求響應無效";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"未能處理授權請求";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"授權請求失敗未知原因";
break;
}
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:errorMsg forKey:@"errorMsg"];
[dic setValue:[NSNumber numberWithInteger:error.code] forKey:@"code"];
if (self.appleLoginBlock)
{
self.appleLoginBlock(AppleLoginTypeFailure,errorMsg,dic);
}
}
#pragma mark ————————————— 告訴代理應該在哪個window 展示內容給用戶 —————————————
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0))
{
return [UIApplication sharedApplication].windows.lastObject;
}
@end
- 調用
#import "ViewController.h"
#import "AppleLogin.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// user在第一次蘋果驗證時傳空,如果對user做了存儲,傳user可以快速驗證(簡單說就是你驗證過的user手機裏會存,並且每次返回的user都是不一樣的,user正確斷網也可以驗證)
NSString *user ;
[AppleLogin appLogoinFromUser:user view:self.view rect:CGRectMake(100, 100, 60, 60) block:^(NSInteger state, NSString * _Nonnull msg, id _Nonnull data) {
if (state == AppleLoginTypeSuccessful)
{
NSLog(@"授權成功 %@",data);
}
else if (state == AppleLoginTypeUserSuccessful)
{
NSLog(@"賬號驗證成功");
}
else
{
NSLog(@"驗證失敗: %@",msg);
}
}];
}
@end