Приложение Facebook Canvas — циклическое перенаправление входа

Я использую шаблон Social Cookbook на основе Python для создания приложения Facebook. , но у меня возникла проблема с поддержкой Canvas, которая выполняет POST вместо GET. В примере Cookbook не указано, как с этим справиться. На основании прочтения этого примера Hello World и глядя на пример Run With Friends, я могу получить подписанный запрос, прочитать данные (идентификатор пользователя, токен) и установить метод GET.

Однако по мере того, как это продолжается, браузер / сервер Tornado входит в цикл, в котором он неоднократно запускает LoginHandler. Выдает мне ошибку «Firefox обнаружил, что сервер перенаправляет запрос на этот адрес таким образом, который никогда не будет выполнен». Я пытался понять это два дня и подумал, что если кто-то может помочь, то это будет StackOverflow. Спасибо за любые рекомендации, которые вы могли бы дать по модификации Social Cookbook для поддержки холста Facebook.

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

person JeffG    schedule 02.06.2012    source источник


Ответы (1)


Итак, вот что я в итоге сделал (благодаря некоторой помощи от oDesk — Haiming Yin) и каковы были некоторые из моих проблем. Во-первых, в системе с запущенным FireFox на Mac были отключены сторонние файлы cookie. Это вызовет проблемы с холстом Facebook. В 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>
person JeffG    schedule 06.06.2012