Нашел хорошую библиотечку, в которой реализована поддержка oAuth 1 & oAuth 2 для iOS/Mac OS. К сожалению, документации по ней нет, зато есть демка использования, в которой реализована поддержка авторизации для twitter, facebook, flickr, qq.
Далее расскажу как я делал авторизацию LinkedIn с ее помощью.
Создаем новый проект "Single View Application", у меня он будет называться "LinkedInAuth".
Подключаем зависимости:
- непосредственно обсуждаемая библиотека (https://github.com/sprhawk/ytoolkit.git)
- SBJson для парсинга json (https://github.com/stig/json-framework.git)
- обертка создания http запросов - ASIHTTPRequest (https://github.com/pokeb/asi-http-request.git) !обязательно прочитатайте как она подключается http://allseeing-i.com/ASIHTTPRequest/Setup-instructions
- так же подключаем еще два файла (ASIHTTPRequest+YOAuthv1Request) из "ytoolkit/externals/asi-http-request additions/"
- добавляем стандартные библиотеки: CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics, Security и libz.
Теперь нужно указать дополнительные флаги линкеру (это требует ytoolkit).
- открываем "Build Settings"
- в разделе "Linking" находим "Other Linker Flags" и добавляем туда "-all_load" и "-ObjC" (если вы не видите "Other Linker Flags" переключите отображение списка на "All")
Нам нужен класс в проекте, в котором будут хранится ключ и секрет от LinkedIn'а. Для этого добавляем новый "Objective-C class" под названием "AuthCredentials", унаследованный от "NSObject". Мы потом уберем обьявленый Xcode'ом интерфейс.
В "AuthCredentials.h" обявлием константы kLinkedInKey и kLinkedInSecret:
#import <Foundation/Foundation.h> #import <ytoolkit/ydefines.h> YEXTERN NSString * const kLinkedInKey; YEXTERN NSString * const kLinkedInSecret;
А в "AuthCredentials.m" указываем значения наших констант:
#import "AuthCredentials.h" NSString * const kLinkedInKey = @"сюда вписываем ключ"; NSString * const kLinkedInSecret = @"а сюда секрет )";
Добавляем в проект новый "Objective-C class", который назовем "AuthViewController" и наследуем от "UIViewController". Также не забываем поставить галку "With XIB for user interface".
Открываем AuthViewController.h и приводим его вот к такому виду:
#import <UIKit/UIKit.h> #import <ytoolkit/ydefines.h> #import "ASIHTTPRequest.h" @class AuthViewController; @protocol AuthViewControllerDelegate - (void)authViewControllerDidFinish:(AuthViewController *)controller; @end @interface AuthViewController : UIViewController <UIWebViewDelegate, ASIHTTPRequestDelegate> @property (assign, nonatomic) id<AuthViewControllerDelegate> delegate; @property (retain, nonatomic) IBOutlet UIWebView *webView; @property (copy, nonatomic) NSString *accesstoken; @property (copy, nonatomic) NSString *tokensecret; @property (copy, nonatomic) NSString *verifier; @property (copy, nonatomic) NSString *step; // нужен что бы в будующем понимать на каком шаге авторизации мы находимся - (IBAction)done:(id)sender; @end
Открываем AuthViewController.xib, добавляем на него WebView и привязываем к нашему webView(с зажатым "control" тянем связть от "File's Owner" до "WebView" и из выпавшего списка выбираем "webView") и в обратном порядке выбирая delegate.
Теперь можно перейти к самой большой части, непосредственно к функционалу авторизации через LinkedIn для этого открываем наш AuthViewController.m и добавляем в него код.
Для начала прописываем нужные импорты:
#import "ASIHTTPRequest+YOAuthv1Request.h" #import "AuthCredentials.h" #import "SBJson/SBJson.h" #import <ytoolkit/ymacros.h> #import <ytoolkit/ycocoaadditions.h> #import <ytoolkit/yoauthadditions.h>
В "viewDidLoad" начинам процедуру авторизации:
// создаем запрос ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"https://api.linkedin.com/uas/oauth/requestToken"]]; request.delegate = self; // указываем что мы будем обрабатывать ответ [request setRequestMethod:@"POST"]; // тип запроса POST // вызываем функцию подготовки запроса, которая добавит нужные параметры в url [request prepareOAuthv1AuthorizationHeaderUsingConsumerKey:kLinkedInKey consumerSecretKey:kLinkedInSecret token:nil tokenSecret:nil signatureMethod:YOAuthv1SignatureMethodHMAC_SHA1 realm:nil verifier:nil callback:@"http://linkedinauth"]; // линк нашего приложения self.step = @"0"; // это первый шаг [request startAsynchronous];
Добавляем метод который покажет ошибку если она произошла:
- (void)requestFailed:(ASIHTTPRequest *)request { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"LinkedIn Auth" message:[request.error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease]; [alert show]; }
И обработчик вернувшегося запроса:
- (void)requestFinished:(ASIHTTPRequest *)request { NSDictionary *params = [request.responseString decodedUrlencodedParameters]; self.accesstoken = [params objectForKey:YOAuthv1OAuthTokenKey]; // забираем токены self.tokensecret = [params objectForKey:YOAuthv1OAuthTokenSecretKey]; if (self.accesstoken && self.tokensecret) { if ([self.step isEqualToString:@"0"]) { // если есть токены и это первый шаг, то открываем страницу авторизации LinekdIn в нашем WebView NSString *url = [NSString stringWithFormat:@"https://www.linkedin.com/uas/oauth/authorize?%@=%@", YOAuthv1OAuthTokenKey, self.accesstoken]; NSMutableURLRequest *r = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; [self.webView loadRequest:r]; } else { // если шаг не первый, то завершаем процесс авторизации [self.delegate authViewControllerDidFinish:self]; } } }
Теперь ловим обновление WebView:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = request.URL; NSString *s = [url absoluteString]; NSString *host = [url host]; // если загружаемый урл принадлежит нашему приложению if ([host isEqualToString:@"linkedinauth"]) { NSDictionary *params = [s queryParameters]; // проверяем не заприщен ли доступ if ([params objectForKey:@"denied"] == nil) { self.verifier = [params objectForKey:YOAuthv1OAuthVerifierKey]; // сохраняем верификационный код ASIHTTPRequest *r = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"https://api.linkedin.com/uas/oauth/accessToken"]]; [r setRequestMethod:@"POST"]; r.delegate = self; // отправляем запрос авторизации наших токенов [r prepareOAuthv1AuthorizationHeaderUsingConsumerKey:kLinkedInKey consumerSecretKey:kLinkedInSecret token:self.accesstoken tokenSecret:self.tokensecret signatureMethod:YOAuthv1SignatureMethodHMAC_SHA1 realm:nil verifier:self.verifier callback:nil]; self.step = @"1"; // дальше пошел второй шаг [r startAsynchronous]; } else { NSString *deniedMsg = [NSString stringWithFormat:@"authorize denied: %@", [params objectForKey:@"denied"]]; UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:[[self class] description] message:deniedMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease]; [alert show]; } return NO; } return YES; }
Вот собственно и все. Осталось только сохранить полученные нами токены. Для этого мы в "ViewController.h" добавляем объявление переменных, импорт контролера авторизации и делегирование AuthViewControllerDelegate:
#import <UIKit/UIKit.h> #import "AuthViewController.h" @interface ViewController : UIViewController <AuthViewControllerDelegate> @property (strong, nonatomic) NSString *accesstoken; @property (strong, nonatomic) NSString *tokensecret; @end
Сохранение полученных значений в "ViewController.m":
- (void)authViewControllerDidFinish:(AuthViewController *)controller { self.accesstoken = controller.accesstoken; self.tokensecret = controller.tokensecret; [self dismissModalViewControllerAnimated:YES]; }
Исходный код: скачать
No comments:
Post a Comment