2012-06-02 1 views
1

나는 Social Cookbook 기반의 Python 기반 템플릿을 사용하여 Facebook 응용 프로그램을 만들었지 만 Canvas support which does a POST instead of a GET에 문제가 있습니다. Cookbook 예제에는이를 처리하는 방법이 포함되어 있지 않습니다. 이 Hello World example을 읽고, Run With Friends 예제를 보면, 서명 된 요청을 받고, 데이터 (사용자 ID, 토큰)를 읽고, 메소드를 GET으로 설정할 수 있습니다.페이스 북의 캔버스 애플 리케이션 - 순환 로그인 리디렉션

그러나 브라우저/토네이도 서버는 계속 진행하면서 반복적으로 LoginHandler를 실행합니다. "Firefox가 서버가이 주소에 대한 요청을 완료되지 않는 방식으로 리디렉션 중임을 감지했습니다."라는 오류 메시지가 나타납니다. 나는이 일을 2 일 동안 알아 내려고 노력해 왔고 누군가가 도울 수 있다면 생각했다. StackOverflow가 될 것이다. 페이스 북의 캔버스를 지원하기 위해 소셜 쿡북을 수정하면서 제공 할 수있는 모든 지침을 주셔서 감사합니다. 무엇을 내 몇 가지 문제가 있었다 -

class BaseHandler(tornado.web.RequestHandler): 

    def initialize(self): 
     self.init_facebook() 

    def init_facebook(self): 
     # initial facebook request comes in as a POST with a signed_request 
     signed_request = self.get_argument('signed_request', None) 
     if signed_request and self.request.method == u'POST': 
      app_secret = options.facebook_app_secret 
      data = load_signed_request(signed_request, app_secret) 
      user_id = data.get(u"user_id") 
      mytoken = data.get(u"oauth_token") 
      print mytoken 
      self.set_secure_cookie("uid", user_id) 
      self.request.method = u'GET' # causes loss of request.POST data 

답변

1

좋아, 그래서 여기에 내가 (Haiming 음과 일부 oDesk의 도움 덕분에)하고 결국 것입니다. 하나는 Mac에서 FireFox를 실행하는 시스템에서 타사 쿠키가 비활성화 된 것입니다. 이것은 Facebook Canvas에 문제를 일으킬 것입니다. IE에서는 적절한 P3P 헤더를 설정해야합니다. 그래서이 모든 것들이 좋은 두통을 일으켰습니다.

class BaseHandler(tornado.web.RequestHandler): 
    @property 
    def prepare(self): 
     self.set_header('P3P', 'CP="HONK"') 

    def initialize(self): 
     if self.request.full_url() == "http://mydomain/a/facebook/": 
      self.request.protocol = "https" 
     self.init_facebook() 

    def init_facebook(self): 
     """Sets up the request specific Facebook and User instance""" 

     # initial facebook request comes in as a POST with a signed_request 
     signed_request = self.get_argument('signed_request', None) 
     if signed_request and self.request.method == u'POST': 
      app_secret = options.facebook_app_secret 
      data = load_signed_request(signed_request, app_secret) 
      user_id = data.get(u"user_id") 
      if user_id: 
       self.set_secure_cookie("uid", user_id) 
      self.request.method = u'GET' 

class FacebookCanvasHandler(HomeHandler): 
    def get(self, *args, **kwds): 
     logging.info("Facebook Canvas called.") 
     if not self.current_user: 
      logging.info("Need user grant permission, redirect to oauth dialog.") 
      logging.info(self.settings.get("facebook_canvas_id")) 
      oauth_url = self.get_login_url(self.settings.get("facebook_canvas_id")) 
      logging.info(oauth_url) 
      self.render("canvas_oauth.html", oauth_url=oauth_url) 
     else: 
      super(FacebookCanvasHandler, self).get(*args, **kwds) 

def load_signed_request(signed_request, app_secret): 
    try: 
     sig, payload = signed_request.split(u'.', 1) 
     sig = base64_url_decode(sig) 
     data = json.loads(base64_url_decode(payload)) 

     expected_sig = hmac.new(app_secret, msg=payload, digestmod=hashlib.sha256).digest() 

     if sig == expected_sig and data[u'issued_at'] > (time.time() - 86400): 
      return data 
     else: 
      return None 
    except ValueError, ex: 
     return None 

def base64_url_decode(data): 
    data = data.encode(u'ascii') 
    data += '=' * (4 - (len(data) % 4)) 
    return base64.urlsafe_b64decode(data) 

canvans_oauth.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <title> 
     Page Title 
    </title> 
    <meta name="description" content="description of the page" /><meta name="keywords" content="" /><meta name="viewport" content="width=device-width" /> 
    <link rel="icon" type="image/png" href="/static/favicon.ico" /> 
    <script> 
     window.top.location = "{% raw oauth_url %}"; 
    </script> 

</head> 

<body id="inner_body" class="inner_body"> 
redirecting to oauth... 
</body> 
</html>