맥부기 펌 : http://cafe.naver.com/mcbugi.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=83209
< Ver 1.0 : 2010.10.06 >
1. 덧글에 Yaji에 대한 질문이 있어 추가했습니다. 추가 방법에 대한건 나중에 다시...^^;;Yaji는 Json파서인데 트위터 검색 API에 보면 데이터를 Json으로만 던져주는 것이 있더군요.언제한번 업뎃해야지~~ 했는데.. 떡본김에 제사지낸다고 오늘 해버렸습니다.단, Yaji 추가하고 컴파일이 오류가 없음만을 체크했기에 실제 제대로 동작하는지는확인을 못했습니다. 문제 있으시면 덧글 남겨주세요. ( iOS용 Yaji Framework를써야하는지 몰라 한참을 헤맸네요 푸헙! )2. 첨부파일 중 withYaji라고 되어 있는 것을 받으시면 1,2 항목이 적용된 것을 보실 수 있습니다.
[2] OAuth/XAuth가 어떤 인증 방식인가요?기존의 Basic 형식의 트위터 연동 방식(파라메터 달고 인증)이 지난달에 완전히 사라지고,오래전부터 지원은 해왔지만 선택적으로 사용하였던 OAuth 방식으로 인증 방식이 바뀌었죠.바뀐 이유는 간단합니다.사용자 정보를 보다 안전하게 인증하기 위한거죠 ^^;
먼저 OAuth는 카페내에 이미 관련글들이 있으니, 자세하게는 그쪽 게시물을 보시구요(^^;;;)간단하게 설명드리자면,서비스를 제공(회원정보 포함)하는 서비스 프로바이더(여기서는 트위터죠)가자신들의 서비스를 여기 저기서 사용하는데 있어서 안전한 인증 절차를 위해 사용하는 하나의 방법론입니다.절차를 순서적으로 대충 그려보자면.[1] 서비스 프로바이더(트위터)에게 제 어플(컨슈머)이 너희 트위터 기능을 사용하고 싶다!!라고 등록을 합니다.(http://dev.twitter.com/apps/new 요기서 어플을 등록하는거죠)[2] 그러면 서비스 프로바이더는 그래 써라!! 라고 키(컨슈머키/컨슈머 시크릿키)를 발급해주죠.(여기까지 하시면 OAuth를 이용하기 위한 준비는 된겁니다.)[3] 그러면 실제 제 어플(컨슈머)은 서비스에서 트위터를 사용할때, 로그인과 글쓰기로 나눠 사용을 하게되죠.[로그인] 어플에서 트위터 사이트의 로그인 창을 띄우고 여기서 사용자가 로그인을 한 후컨슈머키를 엑세스 토큰(Access Token)으로 바꾸는과정을 걸치게 되고, 이 과정이 끝나면 회원 로그인이 끝나는 겁니다.OAuth를 이용한 예제를 보시면 로그인 이후 과정은 자동으로 해결해 줄겁니다.[글쓰기] 글을 쓰기 위해서는 위 [로그인] 절차가 이미 되어 있어야 합니다.글을 트위터에 올릴때는 엑세스 토큰을 이용해 트위터(서비스 프로바이더)가아.. 이 글은 인증된 글이구나.. 하고 인식할 수 있게 해줘야 하는겁니다.[4] 그럼 XAuth는 뭐냐면 기존에 사용자 아이디/비밀번호를 어플에 저장하고, 이를 이용해 인증을 자동으로 처리하던것을 그대로 사용하려면 이를 위해 트위터의 OAuth 뒷문(?)이라고 할 수 있는 XAuth를 이용해야합니다.즉, XAuth는 인증 방식은 OAuth이나 인증을 위해 따로 웹뷰(로그인 창)를 띄우지 않고도 인증이 가능하게끔뒷문을 열어주는 형식이라고 할 수 있습니다.XAuth를 사용하기 위해서는 먼저 OAuth의 등록과정을 거쳐 컨슈머키와 컨슈머시크릿을 발급받고,트위터에 메일을 보내 "나 이런 이런 이유로 이런 어플에서 XAuth를 사용하고 싶다"고 하면,검수과정을 거쳐 XAuth 허용여부를 결정해줍니다.
KeyChain은 유료개발자로 등록하신 분들은 아시겠지만, 맥 OS에서 인증서와 사용자 아이디/비밀번호를 관리하는시스템입니다. 이것이 iOS용으로 아이팟이든 아이폰이든 패드든 적용이 되어 있지요.물론 애플 자체에서 제공하는 만큼 보안성은 애플 자신들이 불신하지 않는한은 안전하다고 볼 수 있습니다.^^;이 문서에서 XAuth를 구현하는데 MGTwitterEngine을 사용하는데,MGTwitterEngine의 예제에 보면 이런 Note가 있습니다."예제에서는 NSUserDefaults에 토큰값을 저장하지만, 되도록이면 KeyChain에 저장하는 것을 권장한다."라고요.솔직히 그냥 NSUserDefaults에 저장해도 상관은 없습니다만,혹시나, 사용자 정보를 그냥 plist파일에 저장해서 사용하시거나 하는분이 있거나,db에 넣되, 암호화/복호화를 거치지 않는 분들을 위한 것이라 보시면 됩니다.자동으로 암호화(바이너리화) 되어 저장되기 때문에 따로 암호화 메서드가 필요 없구요.가져다 쓸때도 그냥 가져다 쓰면 알아서 복호화(문자열) 해주기 때문에 이 메서드 또한 필요가 없습니다.거기다가 아래에 보면 KeyChain에 등록하고 불러오는 External 클래스를 이미 누가 만들어둔게 있어서,이를 이용할테니, 무지 편하죠 ^^;
위에서 말씀드렸듯이 이 문서에서는 키체인을 이용하여 Access Token 정보를 저장하고,이 정보를 이용해서 트위터에 사용자 인증을 하고, 글을 쓰는것 까지 합니다.
준비해야할 것은 크게 3가지입니다. KeyChain을 이용하는 클래스 메서드와트위터 API를 편리하게 사용하고 인증도 함께해주는 MGTwitterEngine,그리고 트위터에서 XAuth를 인증 받는것.1. 트위터에서 XAuth를 인증 받자!!1) http://dev.twitter.com/apps/new 접속, 자신(또는 회사)의 트위터 계정으로 로그인하여 어플을 등록합니다.2) 등록시 다른 부분은 어려움이 없으나, 하나 헷갈리는 부분이 있을겁니다.
3) 위 어플타입인데요, 우리는 XAuth를 이용할 것이기 때문에, Client를 선택해줍니다.5) 메일을 보내면 다음날쯤 검수절차에 들어간다고 메일이 한통오고 이후 2~3일 이내에검수 결과를 다시 알려줄겁니다.6) 컨슈머키값이 바뀌는 일은 없으니, 미리 준비해두세요.2. 트위터 API를 이용하기위해 MGTwitterEngine을 다운로드 받자!!1) aral's XAuthTwitterEngine at master - GitHub 이곳에 가셔서 우측 위에 보시면 다운로드 버튼이 있습니다.2) 써놓고 보니 첨부파일에 있는 것을 그대로 이용하셔도 되네요 ^^;;;3. KeyChain을 이용할 수 있는 편린한 클래스 메서드를 다운로드 받자!!1) 다운로드 사이트는 MGTwitterEngine 예제에도 Note로 코멘트 되어 있습니다.2) (http://github.com/ldandersen/scifihifi-iphone) 에 가셔서 다운로드 받으시면 됩니다.3) 다운로드 받은 파일중에 저희가 필요한 부분은 SFHFKeychainUtils.h와 SFHFKeychainUtils.m 파일뿐입니다.
1) SFHKeychainUtils.h/.m 파일을 프로젝트에 추가합니다.
2) MGTwitterEngine 예제에서 아래 스샷에서 보이는 3개의 폴더를 프로젝트에 추가해 줍니다.
3) 위 3개 폴더 중에 MGTwitterEngine 폴더에 보시면 "YAJL" 이름이 포함된 파일들이 있습니다.이 파일들을 모두 삭제해 줍니다.( 이 파일들은 MGTwitterEngine에서 트위터 API 파싱으로 Json과 XML 2가지를 사용하는데,이 중 Json파싱과 관련된 부분입니다. 하지만, 무슨 이유에서인지 사용을 안하더군요.이전과 달리 기본적으로도 YAJL 사용여부가 사용안함으로 되어 있기도 하구요.아무튼 있으면 에러가 나니 파일들을 삭제해줍니다. )(2010.10.28 추가) Yaji를 이용한 API를 사용하시려면 삭제하시면 안됩니다.
4) MGTwitterEngineGlobalHeader.h 파일에서 #define YAJL_AVAILABLE 0 으로 되어 있지 않다면,값을 0(사용안함)으로 변경해 줍니다.
5) 위에서 언급한대로 MGTwitterEngine에서 Json을 사용하지 않고, XML을 이용하니 XML 관련된라이브러리와 SFHKeychainUtils에서 사용하는 Security.framework를 추가해줍니다.
6) 프로젝트 정보에서 XML 사용을 위한 경로를 설정해줍니다.프로젝트명(맨위 파란색 이름)을 더블 클릭해서 나오는 설정창에 Build탭으로 이동한 후 아래로 쭉 내려서아래 스샷에 보이는 항목대로 설정해줍니다.
문서가 완성될때 함께 올려드릴 예제파일에 보시면 OAuth Access Token을 본래의 예제에 있는NSUserDefaults에 저장하는 대신 KeyChain에 등록하게 되어 있습니다.그 내용대로 사용자 아이디와 비밀번호를 저장하시면 됩니다.
여기서 알려드릴 것은 KeyChain이 어떻게 구성 되어 있는지 입니다.KeyChain은 하나의 Username과 바이너리로 저장되는 Password가 한쌍입니다.여기서 작은 문제점이 생깁니다.KeyChain에서 사용자 비밀번호를 읽어오기 위해서는 그 키 값인 Username을 알아야 하는데,사용자의 Username을 미리 알 수가 없죠.
그래서 제가 생각한 것은 Username을 "xxx_Username"과 "xxx_UserPWD"로 지정하고,각각의 비밀번호에 실제 사용자 Username과 Password를 저장하는 것입니다.
다시 말씀드리면, KeyChain상의 Username과 Password를 배열의 Key값과 Value 값으로 생각하시고,Key 값에 "xxx_Username"과 "xxx_UserPWD"를 지정하고,Value 값에 어플 사용자의 실제 Username과 Password를 저장하는 것이죠.
OAuth의 Access Token 또하는 하나의 Key값으로 정의하고,Value에 실제 토큰값을 저장하면 됩니다.
아래 스샷은 예제파일에서 각각 토큰을 KeyChain에 등록하고, 불러오는 부분입니다.(저장)(로드)
이렇게 등록된 값은 아래 스샷의 경로에 있는 SQLite 파일을 열어보시면 확인이 됩니다.(경로) 맥사용자홈/Library/Application Support/iPhone Simulator(확인)* 위 스샷에서 acct 가 Key값이고, data 부분의 바이너리 데이터가 Value 값이라고 보시면 됩니다.
- 이 부분은 하나씩 설명하자면 무지 지루해질듯하니 ^^;예제 소스 부분을 바로 보여드릴까 합니다.
예제 파일의 XAuthTwitterEngineDemoViewController.m 파일의 내용입니다.
#import "XAuthTwitterEngineDemoViewController.h"
#import "XAuthTwitterEngine.h" // 트위터 엔진
#import "UIAlertView+Helper.h" // 요건 Alert 창을 띄우는 유틸리티성 메서드
#import "SFHFKeychainUtils.h" // 키체인 사용 메서드
@implementation XAuthTwitterEngineDemoViewController
@synthesize usernameTextField, passwordTextField, twitterEngine, sendTweetButton;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
// Sanity check
// 키와 시크릿이 제대로 입력되었나 확인하는 단순한 조건문입니다.
if ([kOAuthConsumerKey isEqualToString:@""] ||
[kOAuthConsumerSecret isEqualToString:@""])
{
NSString *message = @"Please add ...";
UIAlertViewQuick(@"Missing oAuth details", message, @"OK");
}
//
// Initialize the XAuthTwitterEngine.
//
self.twitterEngine = [[XAuthTwitterEngine alloc] initXAuthWithDelegate:self];
self.twitterEngine.consumerKey = kOAuthConsumerKey;
self.twitterEngine.consumerSecret = kOAuthConsumerSecret;
// 아래는 트위터 엔진으로부터 XAuth 인증여부를 확인하는 것입니다.
// isAuthorized로 여부 확인을 하게되면 저~기 아래에 있는 delegate method 중
// - (void) storeCachedTwitterXAuthAccessTokenString: (NSString *)tokenString forUsername:(NSString *)username
// 부분이 호출됩니다. 결국 토큰이 유효한가로 확인하는거죠.
if ([self.twitterEngine isAuthorized])
{
UIAlertViewQuick(@"Cached xAuth token found!", @"This app...", @"OK");
self.sendTweetButton.enabled = YES;
}
// Focus : 이건 그냥 사용자 아이디 텍스트박스로 포커싱해주는겁니다.
[self.usernameTextField becomeFirstResponder];
}
#pragma mark -
#pragma mark Actions
- (IBAction)xAuthAccessTokenRequestButtonTouchUpInside
{
NSString *username = self.usernameTextField.text;
NSString *password = self.passwordTextField.text;
NSLog(@"About ... for username: ]%@[ password: ]%@[.",username, password);
// 입력된 사용자 아이디와 패스워드로 XAuth 인증을 요청하는 겁니다.
// 실제로는 isAuthorized로 확인하여 인증이 되어 있지 않을때만 실행하면 되겠죠.
// 인증 실패시에는 - (void) twitterXAuthConnectionDidFailWithError: (NSError *)error;
// 가 호출됩니다.
[self.twitterEngine exchangeAccessTokenForUsername:username password:password];
}
- (IBAction)sendTestTweetButtonTouchUpInside
{
NSString *tweetText = @"Testing xAuth from the XAuthTwitterEngineDemo!";
NSLog(@"About to send test tweet: \"%@\"", tweetText);
// 트위터에 글을 등록하는 겁니다.
// 간단하네요 ^^;
// 등록이 성공 했을때는 - (void)requestSucceeded:(NSString *)connectionIdentifier
// 가 호출되고,
// 등록이 실패 했을때는 - (void)requestFailed:(NSString *)connectionIdentifier
// withError:(NSError *)error 가 호출됩니다.
[self.twitterEngine sendUpdate:tweetText];
}
#pragma mark -
#pragma mark XAuthTwitterEngineDelegate methods
- (void) storeCachedTwitterXAuthAccessTokenString: (NSString *)tokenString forUsername:(NSString *)username
{
// 제가 문서에 써둔 Note 부분입니다.
// Note: do not use NSUserDefaults to store this in a production environment.
// ===== Use the keychain instead. Check out SFHFKeychainUtils if you want
// an easy to use library. (http://github.com/ldandersen/scifihifi-iphone)
//
NSLog(@"Access token string returned: %@", tokenString);
// 전달받은 토큰값을 키체인에 등록합니다.
[SFHFKeychainUtils storeUsername:kCachedXAuthAccessTokenStringKey
andPassword:tokenString
forServiceName:@"testServiceName"
updateExisting:YES error:nil];
//[[NSUserDefaults standardUserDefaults] setObject:tokenString forKey:kCachedXAuthAccessTokenStringKey];
// Enable the send tweet button.
self.sendTweetButton.enabled = YES; // 이건 그냥 버튼 활성화 해주는거구요.
}
- (NSString *) cachedTwitterXAuthAccessTokenStringForUsername: (NSString *)username;
{
// 토큰 확인용 메서드입니다. 토큰이 없으면 null이 리턴됩니다.
NSString *accessTokenString = [SFHFKeychainUtils getPasswordForUsername:kCachedXAuthAccessTokenStringKey
andServiceName:@"testServiceName" error:nil];
//NSString *accessTokenString = [[NSUserDefaults standardUserDefaults] objectForKey:kCachedXAuthAccessTokenStringKey];
NSLog(@"About to return access token string: %@", accessTokenString);
return accessTokenString;
}
- (void) twitterXAuthConnectionDidFailWithError: (NSError *)error;
{
// 사용자 인증 실패일때 호출되는 메서드입니다.
NSLog(@"Error: %@", error);
UIAlertViewQuick(@"Authentication error", @"Please check....", @"OK");
}
#pragma mark -
#pragma mark MGTwitterEngineDelegate methods
- (void)requestSucceeded:(NSString *)connectionIdentifier
{
NSLog(@"Twitter request succeeded: %@", connectionIdentifier);
UIAlertViewQuick(@"Tweet sent!", @"The tweet...", @"OK");
}
- (void)requestFailed:(NSString *)connectionIdentifier withError:(NSError *)error
{
NSLog(@"Twitter request failed: %@ with error:%@", connectionIdentifier, error);
if ([[error domain] isEqualToString: @"HTTP"])
{
switch ([error code]) {
case 401:
{
// Unauthorized. The user's credentials failed to verify.
UIAlertViewQuick(@"Oops!", @"Your...", @"OK");
break;
}
case 502:
{
// Bad gateway: twitter is down or being upgraded.
UIAlertViewQuick(@"Fail whale!", @"Looks....", @"OK");
break;
}
case 503:
{
// Service unavailable
UIAlertViewQuick(@"Hold your taps!", @"Looks...", @"OK");
break;
}
default:
{
NSString *errorMessage = [[NSString alloc] initWithFormat:
@"%d %@", [error code],
[error localizedDescription]];
UIAlertViewQuick(@"Twitter error!", errorMessage, @"OK");
[errorMessage release];
break;
}
}
}
else
{
switch ([error code]) {
case -1009:
{
UIAlertViewQuick(@"You're offline!", @"Sorry, ...", @"OK");
break;
}
case -1200:
{
UIAlertViewQuick(@"Secure ... failed", @"I ...", @"OK");
break;
}
default:
{
NSString *errorMessage = [[NSString alloc]
initWithFormat:@"%@ xx %d: %@",
[error domain], [error code],
[error localizedDescription]];
UIAlertViewQuick(@"Network Error!", errorMessage , @"OK");
[errorMessage release];
}
}
}
}
예제 파일 내용 그대로의 소스입니다.주석 그대로 달려 있구요 ^^;;
소스 이해 안되시는 부분은 덧글 남겨주세요.
그냥 Tip&Tech 게시판에 쓸까 했습니다만, 셔플이 탐이나 이벤트에 응모도 하고.....므흐흐암튼 사심 있는 게시물입니다! ^^;
1. 첨부 파일은 MGTwitterEngine 예제파일을 그대로 사용하고, 대신 토큰 저장 방식만 KeyChain으로 변경한 겁니다.2. 아.. 이거 글이 길어지니 힘드네요 ㅋ 특히 맥에서 내가 원하는 위치로 이미지가 잘 안올라가서 더 그러네요;;3. 글을 써보니 문씨님의 강좌가 더더욱 대단하게 느껴집니다. 이자릴 빌어 정말 감사드립니다. (__) 정말 도움이 많이 된 강좌들이거든요. 가려운 곳만 삭삭 찾아서 긁어주는 느낌의 강좌랄까요 ㅎㅎ4. 잘못된 내용이나 보정할 부분은 알려주세요 ^^5. [추가1] 메시지(Alert)부분이 길어 지저분해보이길래 다 줄여버렸습니다 ㅡㅡㅋ
나중가면 까먹을거 같아서 일단 메모 형식으로 간단히 남깁니다.
1. http://github.com/gabriel/yajl-objc 요기가 yaji 다운로드 링크이구요.2. http://github.com/lukeredpath/LROAuth2Client/tree/master/Vendor/YAJLIOS.framework 요기가 iOS용 Yaji framework 다운로드 가능한 곳입니다.3. 추가 방법!!
1) MGTwitterEngineGlobalHeader.h 에서 #define YAJL_AVAILABLE 1로 변경2) 위 내용중 Yaji관련된 삭제되었던 파일들 다시 원위치~<title></title>
3) iOS용 Yaji framework를 추가4) MGTwitterYAJLParser.m에서
5)MGTwitterYAJLParser.m 우클릭해서 Get Info 하시면 아마 프로젝트 타켓이 없을 겁니다.<title></title>_handle = yajl_alloc(&callbacks, &cfg, self); 이 부분을
<title></title>
_handle = yajl_alloc(&callbacks, &cfg, nil, self); 로 수정
타켓팅해주기!!(check박스 체크)일단 요까지~ ^^;;;
'애플 > iPhone' 카테고리의 다른 글
iOS 모든 버전의 펌웨어 다운 (0) | 2011.05.05 |
---|---|
팟캐스트(Pod cast) (0) | 2010.11.09 |
아이폰4 배경화면 (0) | 2010.10.27 |
트위터 멘션관계도 확인 사이트 (0) | 2010.10.07 |
구글, '말로 쓰는 문자·채팅·이메일' 발표 (0) | 2010.10.06 |