ABOUT ME

-

Today
-
Yesterday
-
Total
-

OAuth홈페이지에서 제공하는 OAuth인증 흐름도를 보면서 대략적인 과정을 보겠습니다.

일단 용어에 대해 간략히 설명하면 

  • Service Provider : API를 제공하는 쪽입니다. 여기서는 트위터가 서비스프로바이더가 됩니다.
  • Consumer : API를 사용하는 어플리케이션, 여기서는 트위터에 등록한 어플리케이션이 컨슈머입니다.
  • User : 서비스프로바이더 또는 컨슈머를 사용하는 사용자, 트위터 또는 트위터관련 어플을 사용하는 트위터 사용자입니다.

OAuth를 사용하는 이유는 Consumer쪽에서 사용자의 정보(리소스)에 접근하기 위해서 사용자의 비밀번호가 필요하게 됩니다.
  그런데 Consumer에서 악의적으로 사용할 수 있는 위험과  API를 http 요청하는 과정에서 사용자의 비밀번호가 그대로 노출되는 위험 등의 이유로 인해 OAuth라는 방식을 통해 이러한 문제점을 해결하면서 사용자의 정보(리소스)를 Consumer쪽에서 접근할 수 있도록 해주는 방법이 OAuth인증입니다. OpenAPI쪽에서 OAuth가 인증방식의 표준이라고 하네요..

 뭐 암튼 기존에 제공하던 basic인증방식은 모르는 사람한테 집열쇠 맡긴거나 다름 없었나봅니다..

아무튼 그럼 그림의 순서를 보면 

  1. Consumer Requests - Request Token
    : 컨슈머(어플리케이션)가 서비스프로바이더(트위터)에게 리퀘스트 토큰을 요청합니다. 리퀘스트 토큰은 최종적으로 받게될 억세스 토큰을 받기 위해 임시적으로 사용되는 토큰입니다.

  2. Service Provider Grants - Request Token
    : 컨슈머의 요청에 따라 서비스프로바이더는 리퀘스트 토큰을 발급해줍니다.

  3. Consumer Directs User to Service Provider
    : 서비스프로바이더로부터 발급받은 리퀘스트 토큰과 인증URL을 사용자에게 알려주고 사용자가 직접 인증을 하도록 유도(?)합니다.
    사용자는 컨슈머에게 받은 토큰을 가지고 서비스프로바이더에게 직접 접근을 하여 인증을 받습니다.
    사용자가 인증에 성공하면 서비스프로바이더는 사용자에게 verifier(트위터 pin번호)값을 전달합니다.

  4. Service Provider Directs User to Consumer
    : 사용자는 서비스프로바이더로 부터 받은 verifier(pin번호)을 컨슈머에게 알려줍니다.

  5. Comsumer Requests - Access Token
    : 컨슈머는 사용자로 부터 받은 verifier(pin번호)값과 리퀘스트 토큰 등의 정보로 서비스프로바이더에게 억세스 토큰을 요청합니다.

  6. Service Provider Grants - Access Token
    : 서비스 프로바이더는 컨슈머로 받은 요청을 검증하여 최종적으로 사용자의 리소스에 접근할 수 있는 억세스 토큰을 발급합니다.

  7. Comsumer Accesses Protected Resources
    : 컨슈머는 이제 억세스 토큰을 이용하여 사용자의 보호된 리소스에 접근할 수 있습니다.


요약하자면 컨슈머(트위터 어플)은 사용자의 보호된 데이터에 접근하려면 Access Token이 필요하고 , 

이 토큰을 받으려면 서비스프로바이더(트위터)에게 먼저 Request Token을 발급받아야 하고,

컨슈머는 다시 사용자에게 Request Token을 주면서 서비스프로바이더에게 직접 인증을 받아줄 것을 부탁하고,

사용자는 자신의 보호된 데이터를 접근해도 된다는 것을 서비스프로바이더에게 알려 주고,

서비스프로바이더는 사용자가 허락했다는 증명서(pin번호)를 사용자에게 주고,

사용자는 다시 컨슈머에게 증명서를 줘서 컨슈머는 증명서와 Request Token을 가지고 Access Token을 발급해달라고 하면,

서비스프로바이더는 컨슈머가 제출한 자료를 검사하여 이상이 없으면 Access Token을 발급한다.

Access Token을 발급받은 컨슈머는 해당 토큰을 가지고 자유롭게 사용자의 보호된 데이터에 접근할 수 있게 된다.


음... 요약이 된긴 된건지;;;
아무튼 지금까지의 설명은 데스크탑 어플리케이션의 인증과정입니다.  

D.Service Provider Directs User to Consumer 의 과정은 웹 어플리케이션에서는 약간 다릅니다.




▶ liboauth 트위터 인증 예제                                  
그럼 이제 본격적으로 liboauth를 사용하여 트위터 OAuth인증을 해보도록 하겠습니다.
    아래 예제는 사용자인증을 거쳐 Access Token을 획득하여 user timeline 데이터를 가져오는 예제입니다.
* 예제에 나오는 customer key나 token값들은 실제값이 아닙니다.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oauth.h>


/* 응답 메시지 파싱 */
int parse_response(const char* reply, char** token, 
	char** secret, char** username);

int main(int argc, char* argv[])
{
   /*
   * http://dev.twitter.com/apps/new 를 통해 등록한 어플리케이션의 
   * customer key와 customer secret를 설정하시면 됩니다.
   */
   const char 
      *customerKey   = "jWQZH0WTEEyHM0tqDgZd", 
      *customerSecret= "mbgrslyqyJz4V51hT1CJZqL8FUl1wPrIks"; 

   /* twitter api url 목록 */
   const char
      *request_token_url= "http://api.twitter.com/oauth/request_token",
      *authorize_url    = "http://api.twitter.com/oauth/authorize",
      *access_token_url = "http://api.twitter.com/oauth/access_token";

   const char
      *req_uri = NULL,
      *response = NULL;

   /* request token 
   *  트위터에 요청하여 받게될 request token
   */
   char
      *request_token = NULL,
      *request_token_secret = NULL,
      pin[100]={0,};

   /* access token 
   *  트위터에 요청하여 받게된 access token
   */
   char
      *access_token = NULL,
      *access_token_secret = NULL,
      *screen_name = NULL;

   /***
    *	1. request token 요청
    */
   {
      /* request url 생성 */
      req_uri = oauth_sign_url2(
		  request_token_url, NULL, OA_HMAC, NULL, 
		  customerKey, customerSecret, NULL, NULL);
      printf("request token request url:\n\t%s\n", req_uri);

      /* 전송 */
      response = oauth_http_get(req_uri,NULL);
      printf("response:\n\t%s\n", response);

      /* 응답메시지에서 request token, request token secret 추출 */
      parse_response(response, &request_token, 
		  &request_token_secret, NULL);
      printf("request token :\n\t%s\n", request_token);
      printf("request token secret :\n\t%s\n", request_token_secret);
   }
   
   /***
    *	2. 사용자 인증
    */
   {
      /* 사용자 인증 url 생성 
      *  브라우저를 통해 해당 url로 이동한후 사용자 인증을 한다.
      */
      char userAuthUrl[1024]={0,};
      sprintf(userAuthUrl, "%s?oauth_token=%s", 
		  authorize_url, request_token);
      printf("user authorization url:\n%s\n\n", userAuthUrl);
      printf("Enter PIN number:");
      gets(pin);
      printf("PIN number:%s\n", pin);
   }

   /***
    *	3. access token 요청
    */
   {
      /* oauth_verifier(pin번호) 항목 수동 설정
         현재 liboauth는 oauth_verifier항목을 지원하지 않아서 
		 요청url에 해당 항목을 먼저 설정해준후 
		 oauth_sign_url2를 호출합니다.
      */
      char accUrl[1024];
      sprintf(accUrl,"%s?oauth_verifier=%s", access_token_url, pin);
      req_uri = oauth_sign_url2(accUrl, NULL, OA_HMAC, NULL, customerKey, customerSecret,
         request_token, request_token_secret);
      printf("access token request url:\n\t%s\n", req_uri);

      response = oauth_http_get(req_uri,NULL);
      printf("response:\n\t%s\n", response);
  
	  /* 응답메시지에서 access token, access token secret, screen_name 추출 */
      parse_response(response, &access_token, &access_token_secret, &screen_name);
      printf("access token :\n\t%s\n", access_token);
      printf("access token secret :\n\t%s\n", access_token_secret);
      printf("screen name :\n\t%s\n", screen_name);
   }
   
   /***
    *	4. api 사용하기
    * user timeline 가져오기 예
    */
   {
      const char* user_timeline_url = "http://api.twitter.com/1/statuses/user_timeline.xml";
      req_uri = oauth_sign_url2(user_timeline_url,NULL,OA_HMAC,NULL,customerKey,customerSecret,
         access_token,access_token_secret);

	  response = oauth_http_get(req_uri,NULL);
      
      printf("user_timeline xml data:\n%s\n", response);
   }
   return 0;
}

int parse_response(const char* reply, char** token, char** secret, char** username)
{
   int rc,idx;
   char **rv = NULL;
   const char
      *oauth_token = "oauth_token=",
      *oauth_token_secret = "oauth_token_secret=",
      *screen_name = "screen_name=";
   int
      tokenLen = (int)strlen(oauth_token),
      secretLen = (int)strlen(oauth_token_secret),
      nameLen = (int)strlen(screen_name);

   rc = oauth_split_url_parameters(reply, &rv);
   if(rc<=0) return -1;

   for(idx=0; idx<rc; idx++)
   {
      if(token && strncmp(oauth_token, rv[idx], tokenLen)==0 )
      {
         *token = strdup(rv[idx]+tokenLen);
      }
      else if( secret && strncmp(oauth_token_secret, rv[idx], secretLen)==0 )
      {
         *secret = strdup(rv[idx]+secretLen);
      }
      else if( username && strncmp(screen_name, rv[idx], nameLen)==0 )
      {
         *username = strdup(rv[idx]+nameLen);
      }
   }
   if(rv) free(rv);
   return 0;
}


위의 예제에서 사용된 liboauth api는 oauth_sign_url2, oauth_http_get, oauth_split_url_parameters 이렇게 딱 3개입니다.
그리고 중요한 api는 oauth_sign_url2와 oauth_http_get 함수 2개입니다.
일단 예제에서는 http get방식만 다루고 있습니다. post방식에 대해서는 따로 설명하지 않겠습니다.

char *oauth_sign_url2 (const char *url, char **postargs, 
  OAuthMethod method, 
  const char *http_method, 
  const char *c_key, 
  const char *c_secret, 
  const char *t_key, 
  const char *t_secret
  );
  • url
    토큰을 요청한다거나 api사용하여 특정 데이터를 가져온다거나 할때 요청 대상이 되는 url입니다. 
  • postargs
    POST방식 사용시 사용되는 인자입니다. GET방식사용시는 NULL로 설정합니다.
  • method
    요청 파라미터를 어떤 방식으로 암호화하는지를 설정합니다.
    OA_HMAC(hmac-sha1), OA_RSA(rsa), OA_PLAINTEXT(평문) 이렇게 3가지 형식을 지원합니다.
    OA_PLAINTEXT는 https사용시만 가능하고 주로 OA_HMAC를 사용한다고 합니다.
  • http_method
      POST, GET 등의 방식으로 NULL로 설정하는 경우 "GET"으로 처리되고 postargs인자가 NULL이 아닌경우 "POST"로 처리됩니다.
  • c_key
    customer key값
  • c_secret
    customer secret값
  • t_key
    token key값
  • t_secret
    token secret값
  • 리턴값
    OAuth형식에 맞게 생성된 요청uri입니다.  리턴값은 동적할당된 값이기 때문에 사용후 반드시 해제해 주어야 합니다.


char *oauth_http_get (const char *u, const char *q);
  • u
    request url로 oauth_sign_url2로 생성된 url를 사용합니다.
  • q
    추가적인 쿼리스트링을 붙여야하는 경우 해당 인자로 넘겨줍니다. 
  • 리턴값
    서비스프로바이더에서 요청후 응답받은 리턴값입니다. 리턴값은 동적할당된 값이기 때문에 사용후 반드시 해제해 주어야 합니다.

위의 2개 함수를 이용해서 OAuth인증을 하게 되는데 oauth_sign_url2함수가 OAuth인증에 필요한 파라미터값(oauth_signature, oauth_timestamp, oauth_nonce 등등)을 만든 후 실제로 서비스프로바이더에 보내게될 요청 uri를 만들고, oauth_http_get함수로 보낸후 응답(결과값)을 받는 식입니다.


1. Request token 요청
 /* request url 생성 */
      req_uri = oauth_sign_url2(
		  request_token_url, NULL, OA_HMAC, NULL, 
		  customerKey, customerSecret, NULL, NULL);
      printf("request token request url:\n\t%s\n", req_uri);

      /* 전송 */
      response = oauth_http_get(req_uri,NULL);
      printf("response:\n\t%s\n", response);

      /* 응답메시지에서 request token, request token secret 추출 */
      parse_response(response, &request_token, 
		  &request_token_secret, NULL);
      printf("request token :\n\t%s\n", request_token);
      printf("request token secret :\n\t%s\n", request_token_secret);

  Access token을 얻기 위한 첫번째 단계입니다.
oauth_sign_url2에 트위터 request token url인 http://api.twitter.com/oauth/request_token 과 어플리케이션 등록후 받은 customer key와 customer secret값을 설정하여 만들어진 uri를 oauth_http_get함수로 트위터로 보내면 request token을 발급하여줍니다. 
 리턴값은 키=값&키=값.. 의 형태로 되어 있습니다. parse_response함수는 해당 형태의 문자열을 파싱하여 토큰값을 추출하는 역할을 합니다.

request token request url:
http://api.twitter.com/oauth/request_token?oauth_consumer_key=
jWQZH0WTEEyHM0tqDgZd&oauth_nonce=mWt3pyyxUBWkjnp0caZg7hCa1ZO5&
oauth_signature_method=HMAC-SHA1&oauth_timestamp=1283904684&oauth_version=1.0&
oauth_signature=7YYF5L3WXiFL%2BAmeJ5fATzNlkc8%3D

response:
oauth_token=JrjZFiIUQORxHjJqDLyJhfSzngrqrDjuJS2Bisjbk&
oauth_token_secret=Y00zw2Cenqtemw8XpbFq1NkhKIanbWmEgxn3ROHFVU&oauth_callback_confirmed=true

request token :
wtQRiiCWSfUnRTqK01hyfXj0qbjL1WY6grhfn6cu8

request token secret :
Y00zw2Cenqtemw8XpbFq1NkhKIanbWmEgxn3ROHFVU

여기까지의 과정이 그림상의 A,B에 해당합니다.


2. 사용자 인증

/* 사용자 인증 url 생성 
      *  브라우저를 통해 해당 url로 이동한후 사용자 인증을 한다.
      */
      char userAuthUrl[1024]={0,};
      sprintf(userAuthUrl, "%s?oauth_token=%s", authorize_url, request_token);
      printf("user authorization url:\n%s\n\n", userAuthUrl);
      printf("Enter PIN number:");
      gets(pin);
      printf("PIN number:%s\n", pin);
  

인증 url에 request token만 붙이고 해당 url로 사용자가 직접 인증을 한후 PIN번호를 사용자가 입력하는 과정입니다. 
인증을 트위터쪽에서 바로 하기때문에 어플리케이션쪽에서는 사용자의 아이디/비밀번호를 알 수 없는 구조이긴 하지만 사실 어플쪽에서 알려고 하면 방법이 없는것도 아니고 아무튼 인증과정에서 사용자가 끼어들어간다는게 여러모로 불편합니다. 이런 불편함은 데스크탑 어플리케이션쪽에만 해당하는 사항이고 그리고 이런 문제때문에 xAuth란 방식을 제공하고 있습니다. 다만 xAuth를 사용하려면 트위터에 메일을 보내 허락(?)을 받아야 합니다.
이 과정의 그림에서의 C,D에 해당합니다.

user authorization url:
http://api.twitter.com/oauth/authorize?oauth_token=wtQRiiCWSfUnRTqK01hyfXj0qbjL1WY6grhfn6cu8

Enter PIN number:5996657




3. Access Token 요청

/* oauth_verifier(pin번호) 항목 수동 설정
         현재 liboauth는 oauth_verifier항목을 지원하지 않아서 
		 요청url에 해당 항목을 먼저 설정해준후 
		 oauth_sign_url2를 호출합니다.
      */
      char accUrl[1024];
      sprintf(accUrl,"%s?oauth_verifier=%s", access_token_url, pin);
      req_uri = oauth_sign_url2(accUrl, NULL, OA_HMAC, NULL, customerKey, customerSecret,
         request_token, request_token_secret);
      printf("access token request url:\n\t%s\n", req_uri);

      response = oauth_http_get(req_uri,NULL);
      printf("response:\n\t%s\n", response);
  
	  /* 응답메시지에서 access token, access token secret, screen_name 추출 */
      parse_response(response, &access_token, &access_token_secret, &screen_name);
      printf("access token :\n\t%s\n", access_token);
      printf("access token secret :\n\t%s\n", access_token_secret);
      printf("screen name :\n\t%s\n", screen_name);

사용자 인증을 마치고 사용자에게 PIN번호도 받고 access token발급을 위한 모든 준비가 끝났습니다.

access token 요청 url인 http://api.twitter.com/oauth/access_token 과 customer key, secret, request token, secret, pin(oauth_verifier값)을 oauth_sign_url2에 넘겨주면 최종적으로 요청uri를 만들어 주는데 문제는 oauth_sign_url2에는 pin값을 전달받는 인자가 없습니다.
그래서 첫번째 인자인 url을 넘길때 http://api.twitter.com/oauth/access_token?oauth_verifier=pin번호 와 같이 만들어 넘겨주면 됩니다.
이 방법이 불편하신 경우에는 liboauth소스를 수정하시면 됩니다.

아무튼 이제 트위터에 만들어진 uri를 보내면 access token을 발급받게 됩니다.
리턴값에는 access token과 함께 screen_name(사용자id)가 함께 포함되어 있습니다. 그럼 이제 발급받은 이 access_token을 파일이나 DB 등에 잘 저장해 두고 사용하시면 됩니다. 

현재 트위터에서는 access token에 따로 만료기한을 설정하고 있지 않습니다. 특수한 경우가 아닌 이상 한번 받은 토큰으로 계속 사용이 가능합니다.

이 과정의 그림에서 E,F 에 해당합니다.

access token request url:
http://api.twitter.com/oauth/access_token?oauth_consumer_key=jWQZH0WTEEyHM0tqDgZd&oauth_nonce=NF8azpiDkOMST1uWaMv3PGUgkH7RI8&
oauth_signature_method=HMAC-SHA1&oauth_timestamp=1283906365&
oauth_token=wtQRiiCWSfUnRTqK01hyfXj0qbjL1WY6grhfn6cu8&oauth_verifier=5996657&
oauth_version=1.0&oauth_signature=NxjE4AuzJeqGCH%2FT1YaLbGQyqD4%3D

response:
oauth_token=7uqq1sDBwchFK114765419-XkCvUwW7XxOH50EU1ZFh1aV8spw&
oauth_token_secret=PpjW785u2KL4Zf3TYnMw9e6oEEInwRKggavDtCdCctd&user_id=114765419&screen_name=smok95

access token :
7uqq1sDBwchFK114765419-XkCvUwW7XxOH50EU1ZFh1aV8spw

access token secret :
PpjW785u2KL4Zf3TYnMw9e6oEEInwRKggavDtCdCctd

screen name :
smok95


4. API 사용하기 (user timeline 가져오기 예)

const char* user_timeline_url = "http://api.twitter.com/1/statuses/user_timeline.xml";
      req_uri = oauth_sign_url2(user_timeline_url,NULL,OA_HMAC,NULL,customerKey,customerSecret,
         access_token,access_token_secret);
      printf("user timeline request url:\n%s\n", req_uri);
      response = oauth_http_get(req_uri,NULL);
      printf("user_timeline xml data:\n%s\n", response);
 
user timeline request url:
http://api.twitter.com/1/statuses/user_timeline.xml?oauth_consumer_key=jWQZH0WTEEyHM0tqDgZd&oauth_nonce=qCZqJ2W8ZgQpvqTKVFeMWY2kgU&
oauth_signature_method=HMAC-SHA1&oauth_timestamp=1283908341&
oauth_token=7uqq1sDBwchFK114765419-XkCvUwW7XxOH50EU1ZFh1aV8spw&
oauth_version=1.0&oauth_signature=34NBYlwJuJU8JzNALuxAPQt8jdE%3D

<status>
<created_at>Tue Aug 17 13:18:56 +0000 2010</created_at>
<id>21402398564</id>
  <text>&#50612;&#45712;&#49352;..</text>
<source>&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;</source>
<truncated>false</truncated>
<in_reply_to_status_id></in_reply_to_status_id>
<in_reply_to_user_id></in_reply_to_user_id>
<favorited>false</favorited>
<in_reply_to_screen_name></in_reply_to_screen_name>
<retweet_count></retweet_count>

<retweeted>false</retweeted>
<user>
<id>114765419</id>
<name>JK</name>
<screen_name>smok95</screen_name>
<location>Incheon</location>
<description>programmer</description>
<profile_image_url>http://a3.twimg.com/profile_images/1118451467/never_normal.png</profile_image_url>
<url>http://smok95.tistory.com</url>
<protected>false</protected>
<followers_count>5</followers_count>
<profile_background_color>C0DEED</profile_background_color>
<profile_text_color>333333</profile_text_color>
<profile_link_color>0084B4</profile_link_color>
<profile_sidebar_fill_color>DDEEF6</profile_sidebar_fill_color>
<profile_sidebar_border_color>C0DEED</profile_sidebar_border_color>
<friends_count>20</friends_count>
<created_at>Tue Feb 16 14:54:14 +0000 2010</created_at>
<favourites_count>2</favourites_count>
<utc_offset>32400</utc_offset>

<time_zone>Seoul</time_zone>
<profile_background_image_url>http://s.twimg.com/a/1283564528/images/themes/theme1/bg.png</profile_background_image_url>
<profile_background_tile>false</profile_background_tile>
<profile_use_background_image>true</profile_use_background_image>
<notifications>false</notifications>
<geo_enabled>false</geo_enabled>
<verified>false</verified>
<following>false</following>
<statuses_count>33</statuses_count>
<lang>en</lang>
<contributors_enabled>false</contributors_enabled>
<follow_request_sent>false</follow_request_sent>
<listed_count>0</listed_count>
<show_all_inline_media>false</show_all_inline_media>
</user>
<geo/>
<coordinates/>
<place/>
<contributors/>
</status>

실제로 사용자의 timeline을 가져온 모습입니다.




liboauth소스와 예제샘플 그리고 liboauth에서 참조하는 libcurl,openssl 라이브러리를 함께 포함시켰습니다.
Visual Studio 2008을 사용하였습니다.

잘못된 부분은 지적해주시면 감사하겠습니다^^;;





반응형

TAG

댓글 60

  • 이전 댓글 더보기
  • 김태일 2010.10.26 12:04

    안녕하세요.

    먼저 저는 모바일 쪽 회사에서 근무하고 있는 초보 개발자 입니다.

    이번에 c로 트위터 셈플을 만들어야 하는데 (간단한 기능구현, 로그인, 타임라인 받아오기)

    이곳에서 많은 정보를 얻은거 같습니다.

    근데 이런 질문 드려도 될지 모르겠지만

    제가 초보 개발자라서 모르는 게 너무 많아서 지푸라기라도 잡는 심정으로 이렇게 감히 글을 올립니다.

    올려주신 파일 (OAuthTwitSample_liboauthMSVC9.zip) 을 다운받아서 소스를 보았는데

    이걸 실행시려고 하는데 외부 라이브러리를 어떻게 등록해야 하는지를 몰라서 이렇게 여쭤봅니다.

    간단하게 말씀드리면 위의 예제를 어떻게 셋팅해서 실행시키는지를 좀 알려주셨으면 합니다;

    너무 수준 낮은 질물은 해서 죄송합니다만 꼭 좀 부탁드리겠습니다ㅠ

    • Favicon of https://smok95.tistory.com BlogIcon smok95 2010.10.26 19:19 신고

      안녕하세요! 일단
      툴은 VisualStudio 2008을 사용하셔야합니다.
      설치하신후에 sample/liboauthTwitSample/liboauthTwitSample.sln 파일을 여시면 VisualStudio가 열리구요
      그리고 F7 을 누르시면 빌드가 됩니다.
      이상없이 컴파일이 되었으면 F5나 Ctrl+F5로 실행이 가능하구요..
      그냥 실행하실때에는 libcurld.dll, libeay32.dll, ssleay32.dll 파일이 실행파일과 같은 경로에 위치해야 합니다.

      그리고 소스상에서는 일단 어플리케이션 customer key와 customer secret값을 설정해주셔야합니다.
      이값은 트위터에서 어플리케이션을 등록하면 발급받을 수 있구요..
      자세한 내용은 http://smok95.tistory.com/213 을 참고하시면 됩니다.

      2개 값 설정하는거 말고는 일단은 소스상에서 변경할 사항은 없구요..
      질문하신 내용에 맞는 답변인지 모르겠네요^^

  • 박인철 2010.10.26 14:48

    안녕하세요.

    제 문제는 double url encode가 되지 않는 문제였습니다.

    감사합니다 ^^

  • king 2010.11.04 11:03

    정말 큰 도움이 되고 있습니다. 실례가 안된다면 저도 수정 버젼의 twitcurl 받을 수 있을까요? 메일은 myjsbar@nate.com입니다. ^^

  • Rion 2011.02.01 14:32

    안녕하세요.
    트위터를 한창 공부하는 중인데, 덕분에 많은 도움 받고 있습니다.
    질문이 있는데요.
    위의 코드를 통해 API를 사용하는 것 까지는 잘 했는데,
    프로필 등에서 원하는 정보만 가져오게끔 하고 싶은데
    코드 아래 쪽에 있는 파싱 함수를 이해하려 하니 쉽지 않네요.
    막상 사용해보니 '&'를 기준으로 파싱되는 것 같긴 한데...

    • Favicon of https://smok95.tistory.com BlogIcon smok95 2011.03.07 17:49 신고

      음.. 무지 늦었지만요.. 트위터API요청에 대한 리턴값은 xml,json,atom,rss 형식으로 리턴됩니다.

      json은 모든 API를 지원하고 xml은 거의지만 일부 지원하지 않는 API가 있고 atom이나 rss는 약간 지원하는 걸로 알고있습니다.

      일단 api요청시에 xml, json과 같이 url제일끝에 확장자를 붙이는데
      이 붙이는 확장자에따라 리턴데이터 형식이 결정되구요..
      리턴형식에 맞는 파서를 직접만들거나 구해서 파싱작업을 해주셔야합니다.

  • 루니 2011.02.13 09:51

    으악~~ 외국 사이트만 뒤지다가 이렇게 잘 정리된 한글로 된 문서도 있군요 ㅠㅠ(감동) ㅋ

    근데 질문이 있는데요 .ㅎㅎ

    access token 까지 받은 사용자가 있는데

    그 사용자가 보호된 리소스(ex. 트윗타임라인)에 접근을 하려는데 그 사용자가 access token 을 이미 발급받은 사용자인지 아닌지는 어떻게 판단해야 하나요?

  • 워니 2011.03.15 11:21

    안녕하세요 요즘 nate openapi를 사용하려고 하는데 자료가 잘 없네요
    그렇다고 실력이 좋은 것도 아니고
    죄송한데요 liboauth를 찾아 보니 컴파일을 해야 되더군요 근데 ssl도 있어야 하고
    이것 저것 해 봤는데 성공하기 못 했습니다. 혹시 liboauth만들어 놓으신거 있으시면
    k1388@daum.net로 보내주시면 안될까요? 정말 죄송합니다.

  • 익명 2011.06.11 20:13

    비밀댓글입니다

  • 익명 2011.07.08 07:14

    비밀댓글입니다

  • 익명 2011.07.10 14:18

    비밀댓글입니다

  • 익명 2011.07.12 20:13

    비밀댓글입니다

  • 익명 2011.07.12 20:27

    비밀댓글입니다

  • Favicon of https://topnanis.tistory.com BlogIcon 준환이형님 2011.07.27 23:52 신고

    다른 사람들 때문에 하나하나 포스팅하는 일이 쉬운일이 아닌데.. 자세하게 설명해주셔서 잘 따라오게 되었습니다. 감사합니다 ^ㅡ^

  • 아리랑쿠키 2011.09.05 11:42

    안녕하세요 pc에서 트위터 연동 프로그램을 만들고 있는 사람입니다. ㅠ.ㅠ

    올려주신 글을 쭉 보면서 웬만한 다른 구현은 모두 하였는데요 문제가..

    이미지를 업로드 하는 과정에서 일어났습니다. 도무지 3일동안 삽질하고 있어서 질문을 드려요 ㅠ.ㅠ

    tweet을 올리면서 이미지를 올리는 api가 statuses/update_with_media이 있는데요 이게 좀 다른 api와 다른게.

    multipart/form-data이 방식으로 해야한다고 하고 boundary가 경계선으로 쓰인다고 하면서 개발자 페이지에는 나와있고 하여 여러방식으로 해보았지만 되지가 않습니다.. 혹시 구현해보셨는지.. 제발좀 도와주세요 ㅠ.ㅠ

    • Favicon of https://smok95.tistory.com BlogIcon smok95 2011.09.05 16:46 신고

      안녕하세요! api가 새로 추가되었군요 ㅜㅜ;;

      지금 개발하실때 libcurl을 사용하시나요??

      그렇다면 아래 링크 예제 보시고 구현하시면 될것 같습니다.
      http://curl.haxx.se/libcurl/c/multi-post.html

  • 아리랑쿠키 2011.09.05 17:13

    답변 감사합니다 ㅎ ㅠ.ㅠ
    libcurl을 사용하고 현재 지금까지는 twitcurl을 보면서 제작을 하였지만 multipart/from-data 방식으로 전송하는 것은 예제도 없고하여 혼자 사이트 뒤지며 하나씩 해보는 삽질을 하고 있었습니다. 물론 그 소스도 보았지만 이해가 되지 않는 부분이 있어 또 다시 질문 드립니다..

    링크 주신 사이트의 소스는 이미 보고 적용 중이긴 하지만 또 생각되로 안되고 삽질을 하고 있는데요..
    개발자 사이트의 토론 부분을 보면서 짐작하고 넣어봤지만 결과는 생각과는 다르게 나왔습니다.

    일단 문제가 curl_formadd 함수를 사용 할 때 저는

    curl_formadd(&formpost,
    &lastptr,
    CURLFORM_COPYNAME, "status",
    CURLFORM_COPYCONTENTS, "status",
    CURLFORM_END);

    curl_formadd(&formpost,
    &lastptr,
    CURLFORM_COPYNAME, "media[]",
    CURLFORM_FILE, "abcd.png",
    CURLFORM_FILENAME, "abcd.png",
    CURLFORM_CONTENTTYPE, "image/png",
    CURLFORM_END );

    이런 식으로 사용 해봤는데 안되더군요..

    https://dev.twitter.com/discussions/1059?page=1
    위의 개발자 토론 페이지에서의 예제 결과와 비슷하게 나오긴 하지만 결과적으로 인증 실패가 뜨게 됩니다.

  • 아리랑쿠키 2011.09.05 17:49

    답변 감사합니다 ㅎ
    리턴 메시지는 스샷찍어서 영님트윗 멘션으로 올렸습니다.

    지금 제가 의심되는건 curl_formadd 함수를 제대로 사용 했냐와 HttpHeader를 맞게 입력했냐가 의심스럽긴 합니다.

    개발자 토론 페이지의 리플들을 보면 curl 정보에서 boundary값을 경계로 하여 구분을 짓던데

    저는 전혀 그런 것이 없고 boundary값 역시 제가 설정한 값이 아닌 자동으로 입력되어 버리는 값입니다.

    모르는것 투성이네요 ㅠ.ㅠ

  • 아리랑쿠키 2011.09.05 18:51

    온리영님~! 해결했습니다~!!! 으와아아 ~!! 진짜.. 아놔.. 기쁨.. 온리영님한테 질문 드리면서 질문할꺼 생각하고 이것저것 해보다가 해결 했습니다~! ㅠ.ㅠ

    거의 다온걸 URL에 공백하나가 있어서 계속 헤메고 있었네요 ㅠ.ㅠ 크흑..

    감사감사 또감사 드려요 ㅋㅋ 처음 시작부터 여기까지 정말 많은 도움 되었습니다~ 캬하핫

  • 아리랑쿠키 2011.09.07 18:24

    온리영님 덕분에 다시 신나게 개발중입니다. ㅋ 다시한번 감사드립니다 ㅎ
    지금은 정보가 오갈 때 블럭되지 않게 하는거랑 받아온 정보를 어떻게 줄지 고민중이네요 ㅎ

    뭐 이건 생각하고 고민하면 해결 될 듯합니다 ㅋㅋ

    지금 저는 페이스북도 같은 목적으로 한번 만들어 볼까 하는데요 개발자 페이지를 보니 비슷하면서도 다른게 많더군요

    트위터는 ssl을 쓰지 않아도 괜찮았었는데 페이스북은 쓰기도 하고.. 인증 부분도 2.0을 쓴다고는 하는데 차이점도 아직 잘 모르겠구요.. 또 트위터는 웹을 거치지 않아도 잘 되었는데 페이스북은 어떨지도 잘 모르겠구요.. 고민이네요 ㅋㅋ

    일단 트위터부터 마무리 해야할 듯 합니다~ ㅋ 남은 하루 즐겁게 마무리 하시길~ ㅎ

  • 익명 2011.12.05 16:41

    비밀댓글입니다

    • Favicon of https://smok95.tistory.com BlogIcon smok95 2011.12.06 08:59 신고

      오류 메시지가 뭐라고 나오나요?

    • 질문좀 ㅠ 2011.12.07 18:30

      기대하지 않았는데 답변을 주셔서 감사합니다. ㅠㅠ

      const char* user_timeline_url = "http://api.twitter.com/1/statuses/update.xml";
      const char* post_args = "status=hello";

      req_uri = oauth_sign_url2(user_timeline_url, &post_args, OA_HMAC, NULL, customerKey, customerSecret, access_token, access_token_secret);

      라고 해서 실행을 할 경우에 req_uri로(다른 부분은 고치지 않았습니다)

      user_timeline xml data:
      <?xml version="1.0" encoding="UTF-8"?>
      <hash>
      <error>Could not authenticate you.</error>
      <request>/1/statuses/update.xml</request>
      </hash>

      이렇게 반환되어 출력됩니다.
      중간에 <error>Could not authenticate you.</error> 라고 에러가 반환되네요.

      위 방법이 아닌

      const char* user_timeline_url = "http://api.twitter.com/1/statuses/update.xml?status=hello";

      req_uri = oauth_sign_url2(user_timeline_url, NULL, OA_HMAC, NULL, customerKey, customerSecret, access_token, access_token_secret);

      를 한 경우에는

      user_timeline xml data:
      <?xml version="1.0" encoding="UTF-8"?>
      <hash>
      <error>This method requires a POST.</error>
      <request>/1/statuses/update.xml?oauth_consumer_key=b8ZUmBsQBaFgnxtBXcbLYA&amp;
      oauth_nonce=Vo71NmOEVhoWLKT&amp;oauth_signature_method=HMAC-SHA1&amp;oauth_times
      tamp=1323245259&amp;oauth_token=407771142-TsWbd6omOQOQPJNYezneNoLJE7mI7MWE3JGqrk
      gC&amp;oauth_version=1.0&amp;status=hello&amp;oauth_signature=7AZiXeHFmltrAKnQZZ
      z8o3MYNw0%3D</request>
      </hash>

      이렇게하면 statuses/update API에 필요한 추가 파라미터가 없어서 POST를 추가해야 한다고 뜨네요.


    • Favicon of https://smok95.tistory.com BlogIcon smok95 2011.12.09 14:28 신고

      혹시 어플리케이션 인증은 받으셨나요??

  • 익명 2011.12.31 13:54

    비밀댓글입니다

  • BlogIcon Brody 2012.10.19 23:50

    Did you go to university? <a href=" http://stasisfield.com ">can i buy viagra in uk chemist</a> covenantal bond between the patient and the p 1 harmacist.µ