두번째글입니다.
프로그램 설치 및 체험(?)은 아래의 INSTALL NOW을 클릭해주세요 ^^

Alternative content

Get Adobe Flash player


이제 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사이트 로그인페이지로 이동합니다. &#xa;로그인 완료 후, 확인 버튼을 클릭하주세요." 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. 이 짓으로 추석을 날렸습니다-_-;
머드초보 이 작성.

당신의 의견을 작성해 주세요.

  1. Comment RSS : http://mudchobo.tomeii.com/tt/rss/comment/324
  2. aproxacs 2008/09/17 15:54  편집/삭제  댓글 작성  댓글 주소

    안녕하세요~
    AIR로 만드셨네요^^. 와우~ 저도 함 배워봐야겠어요~
    ^^

    • 머드초보 2008/09/17 16:39  편집/삭제  댓글 주소

      앗~ aproxacs님 반가워요~ ^^
      AIR는 데스크탑애플리케이션 제작하는데 매우 쉽게 할 수 있어요^^

      그나저나 스토리큐는 정말 대단한 것 같아요 ^^
      근데 궁금한게 있는데요. aproxacs는 어떻게 읽어요?-_-;

  3. aproxacs 2008/09/17 16:52  편집/삭제  댓글 작성  댓글 주소

    스토리큐에 종종 놀러 오세요. ㅎㅎ
    저는 '아프락삭스'라고 읽어요^^;

    • 머드초보 2008/09/17 17:11  편집/삭제  댓글 주소

      아......그렇게 읽는구나....
      아네 스토리큐에 자주 놀러갈께요 ^^
      스토리큐도 리뷰한번해야겠네요 ^^
      방명록에 글도 남겼어요 ^^

  4. 쿠로 2008/12/25 18:24  편집/삭제  댓글 작성  댓글 주소

    html페이지를 띄워 인증한다음 그데이터를 AIR에서 사용하는것으로 보이는데(AIR Html페이지를 띄우는건 지원하지만).. 그냥 100% Flash와 Actionscript로는 힘들듯보이는데요. 제가생각하는것이 맞는지 궁금하네요.

    • 머드초보 2008/12/26 22:40  편집/삭제  댓글 주소

      아넵! 인증은 꼭 브라우저에서 해야합니다.
      OAuth인증방식은 request토큰을 받으면 그것으로 인증페이지를 연다음에 로그인을 합니다.
      그러면 서버에는 accessToken이 생성되는데, 그것을 가져와서 그것을 이용해서 보호된 자원에 접근하는 방식입니다^^
      로그인은 꼭 브라우저에서 해야하는 것입니다^^

  5. OpenID Logo 들고양이 2009/06/03 18:35  편집/삭제  댓글 작성  댓글 주소

    리스트 가져올 때 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"] 가져오는도중실패했습니다.

    라고뜨는데 왜그럴까요? 알려주세요^_^;

    • 머드초보 2009/06/05 09:31  편집/삭제  댓글 주소

      안녕하세요~
      왜그런지는 모르겠는데, URL에서 www.storyq라고만 되어있네요.
      뭔가 주소를 잘못 입력한 것 같아요
      확인해보세요 ^^

  6. 들고양이 2009/06/08 11:29  편집/삭제  댓글 작성  댓글 주소

    글 상단의 Air프로그램을 설치해서 사용했는데 저런 에러메시지가 떴어요 :) 음...

  7. 들고양이 2009/06/08 21:40  편집/삭제  댓글 작성  댓글 주소

    제가 에러를 덜썼었네요.
    [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은 정확한데 왜그런지는 잘모르겠습니다..

[로그인][오픈아이디란?]
우선 OAuth인증에 대해서.....
잘 모르겠지만, 오픈되어있는 인증인 듯 합니다-_-;(응?)
어쨌든, 이걸 이용해서 인증을 하고, 인증이 되었으면, 보호된 자원으로부터 접근을 할 수 있습니다.
절차는 이렇습니다.

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
머드초보 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]