- notice 스킨변경~
트위터 공식api홈페이지 - http://dev.twitter.com/
OAuth라는 게 2년전에 삽질했던 것이 기억나네요.
트위터도 이 방식으로 인증을 하게 되는데요. 간단하게 동작원리를 설명하면......
1. 연동할 어플리케이션을 등록합니다.
2. 등록하게 되면 Consumer key와 Consumer secret을 발급받습니다.
3. 명시된 Request Token url로 이 키를 이용해 요청하게 되면 인증 url로 가서 이 어플에서 계정접근을 허용할 것인지 묻습니다.
4. 그리고, 허용하게 된다면 Access Token url로 이동해 Access Token을 발급 받습니다.
5. 이 받게 된 AccessToken을 이용해서 해당 어플리케이션은 글쓰고, 정보를 불러올 수 있게 됩니다.
이런 일련의 과정이 있지만, LIbrary가 있으면, 이딴거 몰라도 됩니다-_- 라이브러리가 다 알아서 하니까-_-
일단 앱을 등록합니다.
http://dev.twitter.com/apps/new
application type은 browser로 하고, callback url은 access_token까지 다 받은 다음에 우리 웹사이트로 돌아오기 위한 콜백url을 지정하는 것입니다.
등록을 한 다음에, 해당 애플리케이션의 detail을 보게 되면 consumer key랑 consumer secret이 있습니다.
그리고 라이브러리를 받습니다.
http://github.com/abraham/twitteroauth/downloads
그리고 파일들을 통째로 서버에 올립니다.
그리고, config.php파일을 수정합니다.
consmuer_key랑 consumer_secret을 위에서 등록한 앱의 키값을 등록!
callback은 인증을 하고 accesstoken을 얻은 뒤, 우리 앱으로 돌아올 때 callback url을 지정합니다. 그대로 올렸다면 폴더에 callback.php가 있기 때문에 http://localhost/callback.php가 됨!
그리고, 이제 localhost/index.php를 열고, Sign in with Twitter 클릭하면...
소스를 보게 되면 callback.php에서 AccessToken을 요청해서 받아오게 되는데, AccessToken과 AccessTokenSecret값만 있으면 글을 쓰거나 정보를 가져올 수 있게 됩니다.
이것을 자신의 사이트에 적용을 하게 된다면 db에다가 저장해놓고 쓰게 된다면, 우리사이트의 인증만으로도 트위터에 글을 쓸 수 있게 됩니다.
인증을 취소할 경우를 대비해서 account/verify_credentials api를 요청해 인증이 살아있는지 확인을 해야합니다.
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['oauth_token'], $access_token['oauth_token_secret']);이렇게 connection객체만 가지고 있으면
$connection->post('statuses/update', array('status' => date(DATE_RFC822)));이런 형태로 api를 호출해서 데이터를 가져올 수 있습니다.
[FLEX/AIR] 스토리큐(storyQ)에서 OPEN API사용, OAuth인증받고 데이터가져오기 2/2
Posted in 에어(AIR) // Posted at 2008/09/16 20:29프로그램 설치 및 체험(?)은 아래의 INSTALL NOW을 클릭해주세요 ^^
이제 air프로젝트를 하나 생성합니다.
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" width="300" height="300"
horizontalAlign="center" verticalAlign="middle"
verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:Script>
<![CDATA[
import flash.net.navigateToURL;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import com.mudchobo.MudchoboOAuth;
private var mudchoboOAuth:MudchoboOAuth;
private var consumerToken:String = "자신의 Consumer Token";
private var consumerSecret:String = "자신의 Consumer Secret";
private var requestTokenURL:String = "http://www.storyq.net/oauth/request_token";
private var accesstokenURL:String = "http://www.storyq.net/oauth/access_token";
private var authorizeURL:String = "http://www.storyq.net/oauth/authorize";
private function login():void
{
// RequestToken 요청
mudchoboOAuth = new MudchoboOAuth(consumerToken, consumerSecret);
mudchoboOAuth.requestOAuth(new Object(), requestTokenURL, "POST",
requestTokenResultHandler, requestTokenFaultHandler);
currentState = "stateRequestToken";
}
private function logout():void
{
mudchoboOAuth = null;
currentState = "";
}
private function loginConfirm():void
{
// AccessToken요청
mudchoboOAuth.requestOAuth(new Object(), accesstokenURL, "POST",
accessTokenResultHandler, accessTokenFaultHandler);
}
private function loginCancel():void
{
Alert.show("로그인에 실패했습니다.");
currentState = "stateStart";
}
// RequestToken 요청 성공 시
private function requestTokenResultHandler(event:ResultEvent):void
{
currentState = "stateLogin";
mudchoboOAuth.parseData(event.result.toString());
authorizeHTML.location = mudchoboOAuth.authorizeSite(authorizeURL);
}
// RequestToken 요청 실패 시
private function requestTokenFaultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString() + "요청이 잘못 되었습니다.");
currentState = "stateStart";
}
// AccessToken 요청 성공 시
private function accessTokenResultHandler(event:ResultEvent):void
{
currentState = "stateShowMyQ";
mudchoboOAuth.parseData(event.result.toString());
// 스토리큐에서 자신의 큐리스트를 가져온다.
mudchoboOAuth.requestOAuth(new Object(), "http://www.storyq.net/boxes/mine.xml", "GET",
getQResultHandler, getQFaultHandler);
}
// AccessToken 요청 실패 시
private function accessTokenFaultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString() + "요청이 잘못 되었습니다.");
currentState = "stateStart";
}
// 자신의 큐리스트 가져오기 요청 성공 시
private function getQResultHandler(event:ResultEvent):void
{
dgQ.dataProvider = event.result.boxes.box;
}
// 자신의 큐리스트 가져오기 요청 실패 시
private function getQFaultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString() + "가져오는 도중 실패했습니다.");
}
// 버튼으로 다시 요청하기
private function clickReplyHandler():void
{
mudchoboOAuth.requestOAuth(new Object(), "http://www.storyq.net/boxes/mine.xml", "GET",
getQResultHandler, getQFaultHandler);
}
// 더블클릭 시 해당 큐로 이동
private function doubleClickDgQ():void
{
if (dgQ.selectedItem.uri != null)
{
navigateToURL(new URLRequest(dgQ.selectedItem.uri), "_blank");
}
}
]]>
</mx:Script>
<mx:states>
<mx:State name="stateStart">
<mx:SetProperty name="width" value="300"/>
<mx:SetProperty name="height" value="300"/>
</mx:State>
<mx:State name="stateRequestToken">
<mx:AddChild position="lastChild">
<mx:Label text="잠시만 기다려주세요..."/>
</mx:AddChild>
<mx:SetProperty target="{btnLogin}" name="enabled" value="false"/>
</mx:State>
<mx:State name="stateLogin">
<mx:SetProperty name="width" value="1024"/>
<mx:SetProperty name="height" value="768"/>
<mx:AddChild position="lastChild">
<mx:HTML width="1024" height="642" id="authorizeHTML"/>
</mx:AddChild>
<mx:RemoveChild target="{btnLogin}"/>
<mx:AddChild relativeTo="{authorizeHTML}" position="before">
<mx:HBox id="hbox1">
<mx:Button label="확인" click="loginConfirm()"/>
<mx:Button label="취소" click="loginCancel()"/>
</mx:HBox>
</mx:AddChild>
<mx:AddChild relativeTo="{hbox1}" position="before">
<mx:Text text="아래 창에서 StoryQ사이트 로그인페이지로 이동합니다. 
로그인 완료 후, 확인 버튼을 클릭하주세요." height="40"/>
</mx:AddChild>
</mx:State>
<mx:State name="stateShowMyQ">
<mx:RemoveChild target="{btnLogin}"/>
<mx:AddChild position="lastChild">
<mx:Button label="로그아웃" id="btnLogout" click="logout()"/>
<mx:Button label="다시 가져오기" id="btnReply" click="clickReplyHandler()"/>
</mx:AddChild>
<mx:SetProperty name="width" value="550"/>
<mx:SetProperty name="height" value="422"/>
<mx:AddChild position="lastChild">
<mx:DataGrid width="522" height="328" id="dgQ"
doubleClickEnabled="true" doubleClick="doubleClickDgQ()">
<mx:columns>
<mx:DataGridColumn headerText="제목" dataField="title"/>
<mx:DataGridColumn headerText="주소" dataField="uri"/>
</mx:columns>
</mx:DataGrid>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Button label="스토리큐에 로그인" id="btnLogin" click="login()"/>
</mx:WindowedApplication>
대충만들어서 코드가 지저분합니다만-_-;
아마 알아보실 수 있을듯(응?-_-)합니다.
프로그램을 실행하면, 로그인버튼이 있는데, 로그인 버튼을 클릭하면, 위에서 말한 RequestToken절차가 실행됩니다. RequestToken을 얻어오게 되면, AIR프로그램은 자신의 브라우저를 하나 열어서 로그인 RequestToken을 파라미터로 한 Authorize사이트로 이동합니다.
여기서 사용자는 자신의 아이디로 로그인을 합니다. 로그인이 완료되면, 서버쪽에서 AccessToken을 만들어놓습니다.
로그인 후 위에 확인버튼을 클릭하게 되면, 클라이언트에서는 AccessToken절차가 시작됩니다. AccessToken을 가져온 뒤 그 해당 AccessToken을 이용해 보호된 자원에 접근하는 과정입니다.
접근해서 가져온 데이터는 자신의 큐리스트를 보여주는 겁니다.
자신의 큐들을 데이터그리드에 넣었으며, 그 데이터그리드의 해당 칼럼을 더블클릭하게 되면 해당 큐로 이동하게 됩니다. 정말 별거없네-_-;
위에 코드는 위와 같은 절차로 되어있습니다.
혹시...Oauth로 삽질하시는 분은 이 글로 도움이 되었으면 하네요 ^^
이전 글 링크 - http://mudchobo.tomeii.com/tt/323
PS. 이 짓으로 추석을 날렸습니다-_-;
-
-
머드초보
앗~ aproxacs님 반가워요~ ^^
AIR는 데스크탑애플리케이션 제작하는데 매우 쉽게 할 수 있어요^^
그나저나 스토리큐는 정말 대단한 것 같아요 ^^
근데 궁금한게 있는데요. aproxacs는 어떻게 읽어요?-_-;
-
-
-
머드초보
아......그렇게 읽는구나....
아네 스토리큐에 자주 놀러갈께요 ^^
스토리큐도 리뷰한번해야겠네요 ^^
방명록에 글도 남겼어요 ^^
-
-
쿠로
html페이지를 띄워 인증한다음 그데이터를 AIR에서 사용하는것으로 보이는데(AIR Html페이지를 띄우는건 지원하지만).. 그냥 100% Flash와 Actionscript로는 힘들듯보이는데요. 제가생각하는것이 맞는지 궁금하네요.
-
머드초보
아넵! 인증은 꼭 브라우저에서 해야합니다.
OAuth인증방식은 request토큰을 받으면 그것으로 인증페이지를 연다음에 로그인을 합니다.
그러면 서버에는 accessToken이 생성되는데, 그것을 가져와서 그것을 이용해서 보호된 자원에 접근하는 방식입니다^^
로그인은 꼭 브라우저에서 해야하는 것입니다^^
-
-

들고양이
리스트 가져올 때 RPC Fault faultString="Http request error" faultCode="Server.Error.Request" faultDetail="Error:[IOErrorEvent type="opError" bubbles=false cancelable=false eventPhase=2 text="Error #2032" errorID=2032]. URL:http://www.stroyq/boxes/mine.xml"] 가져오는도중실패했습니다.
라고뜨는데 왜그럴까요? 알려주세요^_^;-
머드초보
안녕하세요~
왜그런지는 모르겠는데, URL에서 www.storyq라고만 되어있네요.
뭔가 주소를 잘못 입력한 것 같아요
확인해보세요 ^^
-
-
-
들고양이
제가 에러를 덜썼었네요.
[RPC Fault faultString="HTTP request error" faultCode="Server.Error.Request" faultDetail="Error: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2032" errorID=2032]. URL: http://www.storyq.net/boxes/mine.xml"]가져오는 도중 실패했습니다.
URL은 정확한데 왜그런지는 잘모르겠습니다.. -
[FLEX/AIR] 스토리큐(storyQ)에서 OPEN API사용, OAuth인증받고 데이터가져오기 1/2
Posted in 에어(AIR) // Posted at 2008/09/16 20:21잘 모르겠지만, 오픈되어있는 인증인 듯 합니다-_-;(응?)
어쨌든, 이걸 이용해서 인증을 하고, 인증이 되었으면, 보호된 자원으로부터 접근을 할 수 있습니다.
절차는 이렇습니다.
1. RequestToken얻어오기.
우선 매쉬업애플리케이션을 등록하면, consumer key와 consumer Secret을 받게 됩니다.
이것과 requestToken요청할 수 있는 주소를 알면 RequestToken을 얻을 수 있습니다.
2. Authorize하기.
RequestToken을 가지고, 인증페이지로 가서 로그인을 합니다. 로그인이 완료되면, 서버프로바이더에서는 해당 RequestToken에 대해서 AccessToken을 준비해놨을겁니다.
3. AccessToken얻어오기.
서버프로바이더가 준비한 AccessToken을 요청합니다. 이건 consumer key, consumer secret, requestToken, requestTokenSecret, AccessToken요청할 수 있는 주소를 알면 얻어올 수 있습니다.
4. 해당 AccessToken을 이용해서 자원에 접근하기.
이 AccessToken이 있으면 해당 자원에 접근할 수 있습니다. 이 토큰으로 보호된 자원에 접근할 수 있는 것이죠.
이런 절차의 인증방식을 사용합니다. 너무 간소화했지만, 여기에 가면 자세히 설명이 있습니다.
http://aproxacs.springnote.com/pages/1279246 (aproxacs님 감사해요~)
AIR에서도 OAuth인증을 사용하는 곳에 인증을 할 수 있습니다.
사실 오픈마루가 제공하는 귓속말을 하려고 했는데, 이건 잘 안되더라구요 ㅠ 운영자님께 문의해놨습니다 ㅠ
스토리큐로 해봅시다 ^^ 이 서비스 정말 획기적인데요? OAuth때문에 처음알았습니다 ^^
여기서 사용한 라이브러리는 as3용 oauth라이브러리 http://code.google.com/p/oauth-as3/와
암호화 라이브러리 http://code.google.com/p/as3crypto/ 를 사용했습니다.
아...소스코드가 너무 기네-_-;
우선 제가 만든 OAuth요청 클래스입니다.
package com.mudchobo
{
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
import org.iotashan.oauth.OAuthConsumer;
import org.iotashan.oauth.OAuthRequest;
import org.iotashan.oauth.OAuthSignatureMethod_HMAC_SHA1;
import org.iotashan.oauth.OAuthToken;
public class MudchoboOAuth
{
private var consumer_key:String;
private var consumer_secret:String;
private var oauth_token:String = "";
private var oauth_token_secret:String = "";
public function MudchoboOAuth(consumer_key:String, consumer_secret:String)
{
this.consumer_key = consumer_key;
this.consumer_secret = consumer_secret;
}
// OAuth요청
public function requestOAuth(params:Object, url:String, method:String,
resultHandler:Function, faultHandler:Function):void
{
var consumerToken:OAuthConsumer = new OAuthConsumer(consumer_key, consumer_secret);
var oauthToken:OAuthToken = null;
if (oauth_token != "")
{
oauthToken = new OAuthToken(oauth_token, oauth_token_secret);
}
var request:OAuthRequest = new OAuthRequest(
method, url, params, consumerToken, oauthToken);
var builtUrl:String = request.buildRequest(new OAuthSignatureMethod_HMAC_SHA1());
trace(builtUrl);
var requestHTTPService:HTTPService = new HTTPService();
requestHTTPService.url = url;
requestHTTPService.method = method;
requestHTTPService.addEventListener(ResultEvent.RESULT, resultHandler);
requestHTTPService.addEventListener(FaultEvent.FAULT, faultHandler);
requestHTTPService.send(params);
}
// Authorize를 위한 로그인 사이트 주소 리턴.
public function authorizeSite(authrizeURL:String):String
{
return authrizeURL + "?oauth_token=" + oauth_token;
}
// Data파싱 후 oauthToken과 oauthTokenSecret추출
public function parseData(data:String):void
{
var tokenStart:Number = data.indexOf("oauth_token");
var tokenEnd:Number = data.indexOf("&oauth_token_secret");
this.oauth_token = data.substring(tokenStart + 12, tokenEnd);
this.oauth_token_secret = data.substring(tokenEnd + 20);
}
}
}
메소드중에 requestOAuth메소드가 있는데, 이것은 parameter와 url, method, resultHandler, faultHandler만 지정해주면 자동으로 OAuth에 필요한 파라메터를 만들어서 요청해주는 메소드입니다.
이걸로 RequestToken, AccessToken, 그 외 보호된 자원에 접근하기 위한 요청으로 쓸 수 있습니다.
authorizeSite메소드는 로그인 해주는 사이트로 이동할 때, requestToken을 파라메터로 붙여주는 주소를 리턴해줍니다.
parseData메소드는 요청 후 리턴받은 데이터가 oauth_token=~~~~&oauth_token_secret=~~~ 라고 되어있는 것을 단순히 파싱해서 변수에 저장하는 역할을 합니다.(참고로, 오픈마루의 귓속말서비스 같은 경우 AccessToken을 요청할 때 뒤에 오픈아이디를 같이 붙여줘서 리턴값이 틀립니다. 그걸 참고해서 저걸 사용해야할 듯 싶습니다.)
글이 너무 길어져서 다음글로 패스-_-;
http://mudchobo.tomeii.com/tt/324


