넷빈즈에서는 RESTful 웹서비스를 손쉽게 만들 수 있습니다.
RESTful은 기존에 사용하던 SOAP/WSDL-based의 WebService와 다르게 매우 간단하게 HTTP를 통해서 자원을 접근할 수 있습니다. 넷빈즈 웹서비스관련문서페이지에는 이렇게 써있군요.

  • REST-based. REpresentational State Transfer is a new way to create and communicate with web services. In REST, resources have URIs and are manipulated through HTTP header operations. For more details, see RESTful Web Services.
  • SOAP/WSDL-based. In traditional web service models, web service interfaces are exposed through WSDL documents (a type of XML), which have URLs. Subsequent message exchange is in SOAP, another type of XML document. For more details, see SOAP-based Web Services.

기존 SOAP/WSDL-based는 WSDL이라는 문서에 정의된 것을 바탕으로 데이터를 요청하고, 요청한 결과를 리턴받는 것 같았습니다. 그리고 데이터를 주고받기 위해서 SOAP이라는 프로토콜을 사용했습니다. 그 프로토콜에 의하면 무슨 봉투만들고, 정의된 표준에 의해서 리턴값을 만들어야 하는 점이 있었는데요.

이 RESTful방식은 자원이 uri를 가지고 있는데요. 그냥 http요청으로 해당 자원 uri를 요청하는데, method를 get, put, delete, post를 이용해 직관적으로 자원에 접근하는 듯 합니다. 아직 잘 모르겠네요-_-; DB랑 연동해서 삽질해보려니 힘들어서 우선 제가 제일 좋아하는 sayHello만 찍어봤습니다-_-;

참고자료
넷빈즈 웹서비스 관련문서페이지
http://www.netbeans.org/kb/61/websvc/intro-ws.html

1. 느리고 답답한 넷빈즈6.1이 필요합니다.

2. New Project -> Web -> Web Application, ProjectName은 HelloWS, Next!

3. Server는 GlashFish V2로 합니다. tomcat으로는 여기서도 아마 테스트를 지원하지 않을 듯 합니다. Finish!

4. HelloWS프로젝트 이름에 대고, 오른쪽버튼 New -> Other -> Web Services -> RESTful Web Services from Patterns선택, Sinleton선택 Next!

5. Resource Package는 자기가 원하는 대로! 저는 com.mudchobo.hello,
Resource Name은 Hello. 이것만 고치면 아래는 자동으로 고쳐집니다. Path부분이 해당 자원의 uri가 됩니다. Finish!
만들어진 소스코드를 보면 HelloResource라는 클래스가 생성되었습니다. @Path("hello")라는 어노테이션이 붙었는데요. HelloResource라는 자원은 /hello로 접근하는 자원이라는 것을 지정해주는 겁니다.
이 HelloResource에는 2가지 메소드가 자동으로 만들어졌습니다. GET과 PUT인데요.
우리가 만들것은 parameter로 name을 받아서 Hello! name 을 리턴하는 것을 만들껀데요. 그러면 GET메소드를 수정해야합니다.

[code]@GET
    @ProduceMime("application/xml")
    public String getXml(
            @QueryParam("name")
            @DefaultValue("NONE")
            String name) {
        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><hello>Hello! " + name + "</hello>";
    }
[/code]
QueryParm어노테이션은 http요청 시 요청파라메터구요. 이건 name으로 받습니다. DefaultValue는 NONE로 했습니다.
보통 자원에 접근하는 주소는 아래와 같이 되더군요.
http://localhost:8080/HelloWS/resources/자원URI
hello자원은 http://localhost:8080/HelloWS/resources/hello이더군요.

저렇게 바꾸었으면 테스트를 할 수 있습니다. GlassFish가 테스트를 너무 잘 지원해줘서 참 좋습니다.

사용자 삽입 이미지

HelloResource클래스에 GET과 PUT이 있기때문에 2개가 나옵니다. 아래는 테스트결과로 리턴받는 값을 실제로 볼 수 있습니다. http Monitor도 있어서 요청한 값, 리턴값을 다 볼 수 있습니다.

이제 다른 클라이언트에서 사용할 수 있습니다. Flex에서 요청하신다면...이건 SOAP WSDL방식이 아니기 때문에 <WebService>를 사용하는 것이 아니라 <HTTPService>를 사용해야합니다.
[code]<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">

    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            private function click():void
            {
                service.send({name: inputName.text});
            }
           
            private function result(event:ResultEvent):void
            {
                 labelResult.text = event.result.hello;
            }
        ]]>
    </mx:Script>
    <mx:HTTPService id="service" method="GET"
        url="http://localhost:8080/HelloWS/resources/hello"
        result="result(event)" />
       
    <mx:TextInput id="inputName" />
    <mx:Button label="확인" click="click()"/>
    <mx:Label id="labelResult" />
   
</mx:WindowedApplication>
[/code]
해당 자원주소에 method를 지정해주고 파라메터로 name을 넘기면 됩니다.
그럼 리턴값은 xml로 받게 됩니다.

제가 잘 몰라서 그러는데, 잘못된 점 있으면 태클걸어주세요-_-; 아직도 잘 모르겠네-_-;
아졸려...-_-;


 
Posted by 머드초보
,
 
입을 옷이 없었는데 잘 됐습니다. 하지만.......반팔이군요-_-; 날씨가 추워졌는데-_-;

뭐 어쨌든, 갔다왔습니다. 평일인데도 많은 분들이 오셨더라구요. 저는 버스가 얼마나 걸리는지 몰라서 빨리나왔는데 버스가 의외로 빨리 도착하는 바람에 12시20분쯤 도착했습니다. 더욱 신기했던 것은.......교보타워 엘리베이터......완전 빠르네요-_-; 예전에 포스코 엘리베이터도 완전 빠르던데....엘리베이터가 빠른 게 부러운 이유는 우리회사 있는 엘리베이터는......거북이처럼 느리기 때문이죠. 점심시간에 재수없으면 10분걸려서 올라가야하는 일이 생기기도 하죠 ㅠ 얘기가 갑자기 삼천포로 빠졌습니다만-_-;

23층에 올라갔습니다. 와우 핸드폰줄입니다. 하나 더 달라고 하고 싶었지만, 소심해서-_-;

사용자 삽입 이미지

제가 1등인줄알고 혼잣말로 "1등인가......" 라고 하니 도우미분께서 "안에 몇 분 와계세요." 그러시더라구요. 아....6등입니다-_-; 설문지를 작성하면 티셔츠를 준다고 하더군요. 사실 강의평도 안하고 그냥 작성해서 내고 싶었습니다만, 끝까지 기다렸습니다.
사용자 삽입 이미지

6등으로 온 증거-_-; 오른쪽에 한 분 더 계셨습니다-_-;



사람들이 막 모이더니 어느새 자리가 꽉 찼더군요. 우와....자리가 없어서 뒤에 서서 보신 분들도 계시더라구요.

우선 영상을 보여줬는데요. Adobe AIR 주제를 가지고, 투어를 하며 사람들에게 홍보를 하는 영상을 보여줬는데 편집이 예술이고 영상미가 꽤 있어보였습니다. 역시 외국은 다르군요. 매우 멋졌습니다.

시작은 어도비사의 어떤 전무님이 말씀으로 시작하셨습니다. 이 분께서 하신 말씀은 최근에 나온 CS4를 자랑 하는 제품 자랑으로 시작했습니다. RIA기술로 구현한 프로젝트가 성공했다는 얘기를 한 듯 합니다 ^^

이제 마이크 챔버스랑 라이언스트어트의 강연이 시작되었습니다.
꽤나 준비를 많이 하신 것 같습니다. 강의 진행방식은 마이크와 라이언이 말을 하면, 통역하시는 분이 통역으로 얘기를 해줍니다. 예전에 JCO에서는 외국인 강연은......그냥 외국인 혼자서 얘기하는 강연을 들은 적이 있었습니다만, 이렇게 Adobe에서는 동시 통역을 준비해줬군요. 대단합니다 ^^

우선 이분들은 새로 나올 신기술에 대해서 소개를 해줬는데요. 저는 곧 나오는 것들인 줄 알았습니다만-_-; 2009월 하반기가 예정이라는 군요? 1년넘게 남았다는 얘기죠 ^^

암튼, 나중에 나올 기술등에 대해서 소개를 해줬는데요. Flash Player 10, AIR 1.5, Flex4를 얘기해줬습니다. 외국분들은 PPT를 잘 만드는 것 같아요. 딱 핵심 포인트만 포인트에 적어 놓는데, 파워포인트의 정석이죠. 외국 ppt를 보면 정말 잘 지키는 것 같아요. 국내에 글씨만 무성히 많은 PPT가 참 많은데, 그건 발표하는 동안, 발표자의 말을 들으라는 건지, 저걸 다 읽으라는 건지 그런 경우가 참 많았거든요. 또 자꾸 얘기가 샙니다만-_-;

암튼, 3D를 사용한 어플리케이션을 많이 보여주셨는데, 여기저기서 환호성이 터져나왔네요. 저도 신기했구요^^ z축을 이용해서 구현이 가능한 것 같아요. Flex Store라는 예제를 보여주셨는데, 핸드폰이 막 쓰리디로 정렬되면서 멋진 장면이 연출 되더군요. 저는 언제쯤 그런 걸 구현할까요-_-;

근데, 일본에서 발표하고 왔는지, 일본어로 된 데이터로 Flash Player10 Text 기능을 보여주더라구요. 일본에 역시 먼저 갔다왔군요. 일본에 대해서 참 부러운 건 JDK를 일본어를 공식 지원한다는것-_-; 그 외에도 Flex Builder를 보면 일본어를 공식 지원해요-_-; 우리나라도 공식 지원해줘요! MS는 한국어판 다 내는데 ^^ Adobe도 내주세욤!

AIR1.5부터는 리눅스를 공식 지원한다고 하는군요. 예전에 리눅스에서 AIR를 한 번 돌려봤는데 잘 돌아갔었습니다. 이제 대표적인 OS는 다 지원하는군요. 멋집니다. 이제 크로스플랫폼이라고 제대로 불리울 수 있겠군요^^

좀 있다 마이클 챔버스가 나왔습니다.
이 분이 얘기하신 것 중에...Vectors라는 자료형이 나왔습니다. 이거 왠지 java의 Vector인가...라는 생각이 들었습니다. Array랑 비슷한 것 같은데요. Vectors도 보니까 Array처럼 쓰지만, 이 놈은 하나의 자료형으로 사용할 수 있는 것 같습니다. 자바에서 제너릭(Generic)문법처럼 쓰더라구요.
[code]var v:Vectors.<Number>
[/code]
얼핏 보고 왔는데.....저런식으로 쓰는 것 같았어요. 우선 Array처럼 v[i] 형태로 사용하구요. 성능차이를 보여줬는데, Vectors가 훨씬 빨랐어요. 효율문제로 저걸 만들었나봐요. 저도 잘 모르겠네요^^

그리고, Flash Player10에서의 개발자들에게 편해진 점들을 소개해주셨는데요. 성능문제로 Drawing APIs에서 여러번 함수를 콜해야하는 것을 단 한번콜하게 하는 것, Local File Access로 전 버전보다 손쉽게 파일 읽고 쓸 수 있구요, 이번에 Pixel Bender라는 것을 지원하게 되었는데요. 아직 감은 안잡힙니다만, 포토샵의 필터같습니다.
이미지나, 동영상 등에 스캔라인 필터를 줄 수 있습니다. 사운드도 된다고 하네요. 코드를 보니, output, input 같은 게 존재하고, 언어는 왠지 as3랑 달라보였습니다만-_-; 나중에 김춘경님이 Pixel Bender에 대해서 발표준비를 하셨더라구요. 우와 이걸 어떻게 알고 준비하셨는지 대단합니다 ^^

아....그 다음 제가 관심을 가지고 있는 것이 Flex4인데, 이거에 대해서도 간략히 설명했는데요. FXG라는 것을 지원한다고 합니다. FXG는 xml기반의 그래픽 인터체인지 포맷인데요. 그래픽을 xml형태로 나타낼 수 있더라구요. MS의 XAML과 비슷한 듯 합니다-_-; 누가따라한거지-_-; 이것으로 디자이너와 개발자를 분리하겠다는 것 같습니다. MS세미나에서도 같은 얘기를 했었는데.....
Flex4에서 스킨입히는 게 더 손쉬워졌다고 하네요. 그리고, state가 향상되었다고 하는데, 예전에 state코드를 보면 매우 지저분하게 생성되는 경우가 많은데, 마이크가 직접 3와 4의 차이점을 보여줬는데, 매우 간결하게 state코드를 쓸 수 있는 것 같습니다.

http://www.tostring.org/에 대해서도 언급했는데요. 열이아빠님이 열심히 번역하신 게 보니까 이거더라구요^^ 열이아빠님 대단합니다 ^^

이제 라이언이 Thermo(써모)를 맛보기로 보여주시기 위해 나왔습니다. 이건 디자이너를 위한 툴이라고 설명을 하는군요. 정말 멋진 툴입니다. 디자이너들이 디자인 후 버튼으로 변경하면 버튼이 되버립니다. 아직 초기단계라서 언제 나올지는 미지수군요 ^^ 보여주면서도 에러가 발생했는지 잘 안되는 부분도 있는 듯 했습니다만-_-;

암튼, 이 외국에서 오신 이 두분의 멋진 발표 재미있었습니다. 신기술은 언제나 즐겁죠. 새로운 정보를 많이 알게 된 것 같아서 즐거웠습니다 ^^

커피랑 도넛타임이였습니다. 배가 고팠는데 참 잘 되었습니다-_-; 도넛을 한 개 먹으니.....배가 고파서 하나 더 먹으려고 했는데, 다 가져가버렸다는....ㅠㅠ

이제 발표자들이 발표할 시간입니다. 아까 마이크와 라이언 발표끝나고 간 사람들이 많더군요. 그 두분을 보려고 오신 분들이 꽤 된 것 같았습니다. 저는 끝까지 자리를.....(티셔츠를......-_-)

오창훈님이 AIR로 만드는 메쉬업 애플리케이션 이야기라는 주제로 발표하셨는데, 조금 뭔가 부족했습니다. 그냥 몇가지 메쉬업을 소개하고 끝난 것 같습니다.

그 다음 이희덕님이 AIR로 만든 모두의 브라우저라는 주제로 발표하셨습니다. 재미있게 발표하시는 것 같습니다. AIR로 크롬형태로 구현하려고 한 것 같습니다(크롬의 스피드는 AIR로 구현하기 힘들겠죠^^). 굉장히 인상깊었던 것은 RIA는 ???????다 라는 것의 빈칸을 핸드폰 문자로 보내면 그걸가지고 추첨을 하는 프로그램을 만들었더라구요^^ 대단합니다 ^^ 직접 준비해놓은 상품을 줬습니다 ^^ 준비를 많이 하신 것 같아요^^

마지막으로 김춘경님이 Pixel Bender소개와 사용이라는 주제로 발표하셨는데, 너무 내용이 어려웠습니다-_-; 뭔소리인지 하나도 몰르겠습니다. 암튼 FlashPlayer10의 새로 추가된 기능인 것 같구요. 마이크챔버스도 잠깐 언급했는데, Photoshop이나 Premiere에서 사용하는 필터기능 같습니다. 암튼 신기했습니다 ^^

오늘 보고 나서 느낀 점은 어서 내공을 쌓아야겠다는 생각이 드는군요. 저도 좋은 주제가 생기면 발표하고 싶습니다만-_-; 능력이 될런지-_-; 내년에 나올 신기술을 미리 볼 수 있어서 좋았구요. 다음에 3rd행사도 어서 빨리 했으면 좋겠네요 ^^

아래는 티셔츠입니다. 뒤에는 air주소가 적혀있네요 ^^.
사용자 삽입 이미지
사용자 삽입 이미지

 
Posted by 머드초보
,
 
이건뭐 설명이 필요없네요.
아까 전시간에 만든 WebService를 호출해봅시다.

전시간에 만들어 놓은 웹서비스
http://mudchobo.tomeii.com/tt/328

플렉스빌더를 실행합니다.
Air로 프로젝트를 하나 만듭니다.
[code]
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical">
   
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
           
            private function callWebService():void
            {
                helloWebService.sayHello(input.text);
            }
           
            private function resultHandler(event:ResultEvent):void
            {
                Alert.show(event.result.toString());   
            }
           
            private function faultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.message);   
            }
        ]]>
    </mx:Script>
   
    <mx:WebService id="helloWebService"
        wsdl="http://localhost:9080/HelloWebApp/HelloService?WSDL"
        useProxy="false"
        result="resultHandler(event)"
        fault="faultHandler(event)" />
       
    <mx:TextInput id="input" enter="callWebService()"/>
    <mx:Button id="button" label="Button" click="callWebService()"/>
       
</mx:WindowedApplication>
[/code]
wsdl부분에서만 주소를 WSDL파일 주소로 써주세요.
그 외에는 RemoteObject나 HTTPService와 같이 같은 방식으로 해주면 돼요.

다음엔 RESTful이 뭔지 좀 알아봐야겠습니다.

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

Alternative content

Get Adobe Flash player


이제 air프로젝트를 하나 생성합니다.
[code]
<?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>
[/code]
대충만들어서 코드가 지저분합니다만-_-;
아마 알아보실 수 있을듯(응?-_-)합니다.

프로그램을 실행하면, 로그인버튼이 있는데, 로그인 버튼을 클릭하면, 위에서 말한 RequestToken절차가 실행됩니다. RequestToken을 얻어오게 되면, AIR프로그램은 자신의 브라우저를 하나 열어서 로그인 RequestToken을 파라미터로 한 Authorize사이트로 이동합니다.
여기서 사용자는 자신의 아이디로 로그인을 합니다. 로그인이 완료되면, 서버쪽에서 AccessToken을 만들어놓습니다.
로그인 후 위에 확인버튼을 클릭하게 되면, 클라이언트에서는 AccessToken절차가 시작됩니다. AccessToken을 가져온 뒤 그 해당 AccessToken을 이용해 보호된 자원에 접근하는 과정입니다.

접근해서 가져온 데이터는 자신의 큐리스트를 보여주는 겁니다.
자신의 큐들을 데이터그리드에 넣었으며, 그 데이터그리드의 해당 칼럼을 더블클릭하게 되면 해당 큐로 이동하게 됩니다. 정말 별거없네-_-;

위에 코드는 위와 같은 절차로 되어있습니다.
혹시...Oauth로 삽질하시는 분은 이 글로 도움이 되었으면 하네요 ^^

이전 글 링크 - http://mudchobo.tomeii.com/tt/323
PS. 이 짓으로 추석을 날렸습니다-_-;
 
Posted by 머드초보
,
 
우선 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요청 클래스입니다.
[code]
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);
        }
    }
}
[/code]
메소드중에 requestOAuth메소드가 있는데, 이것은 parameter와 url, method, resultHandler, faultHandler만 지정해주면 자동으로 OAuth에 필요한 파라메터를 만들어서 요청해주는 메소드입니다.
이걸로 RequestToken, AccessToken, 그 외 보호된 자원에 접근하기 위한 요청으로 쓸 수 있습니다.

authorizeSite메소드는 로그인 해주는 사이트로 이동할 때, requestToken을 파라메터로 붙여주는 주소를 리턴해줍니다.

parseData메소드는 요청 후 리턴받은 데이터가 oauth_token=~~~~&oauth_token_secret=~~~ 라고 되어있는 것을 단순히 파싱해서 변수에 저장하는 역할을 합니다.(참고로, 오픈마루의 귓속말서비스 같은 경우 AccessToken을 요청할 때 뒤에 오픈아이디를 같이 붙여줘서 리턴값이 틀립니다. 그걸 참고해서 저걸 사용해야할 듯 싶습니다.)

글이 너무 길어져서 다음글로 패스-_-;
http://mudchobo.tomeii.com/tt/324
 
Posted by 머드초보
,