为什么current_user无?

时间:2011-10-04 20:37:03

标签: google-app-engine facebook-graph-api facebook

我有一个可怕的bug,我放了一个bounty on,现在我正在减少最简单的复制。至少有一个可以重现它:D一些信息:实体FUser没有填充实体,javascript按钮在登录/注销之间切换,并且从日志中你可以告诉我流程有什么问题。

2011-10-04 17:34:14.398 /example 200 10ms 0cpu_ms 0kb Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20100101 Firefox/4.0

213.89.134.0 - - [04/Oct/2011:13:34:14 -0700] "GET /example HTTP/1.1" 200 694 - "Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20100101 Firefox/4.0" "www.koolbusiness.com" ms=11 cpu_ms=0 api_cpu_ms=0 cpm_usd=0.000157 instance=00c61b117c837db085d58acd70ffae167a06

D 2011-10-04 17:34:14.395

logging current_userNone

的.py

"""A barebones AppEngine application that uses Facebook for login."""

FACEBOOK_APP_ID = "164355773607006"
FACEBOOK_APP_SECRET = "642f15e4324b45661e1049d5b139cb0"

import facebook
import os.path
import wsgiref.handlers
import logging
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template


class FUser(db.Model):
    id = db.StringProperty(required=True)
    created = db.DateTimeProperty(auto_now_add=True)
    updated = db.DateTimeProperty(auto_now=True)
    name = db.StringProperty(required=True)
    profile_url = db.StringProperty(required=True)
    access_token = db.StringProperty(required=True)


class BaseHandler(webapp.RequestHandler):
    """Provides access to the active Facebook user in self.current_user

    The property is lazy-loaded on first access, using the cookie saved
    by the Facebook JavaScript SDK to determine the user ID of the active
    user. See http://developers.facebook.com/docs/authentication/ for
    more information.
    """
    @property
    def current_user(self):
        if not hasattr(self, "_current_user"):
            self._current_user = None
            cookie = facebook.get_user_from_cookie(
                self.request.cookies, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET)
        logging.debug("logging cookie"+str(cookie))
            if cookie:
                # Store a local instance of the user data so we don't need
                # a round-trip to Facebook on every request
                user = FUser.get_by_key_name(cookie["uid"])
                logging.debug("user "+str(user))

                if not user:
                    graph = facebook.GraphAPI(cookie["access_token"])
                    profile = graph.get_object("me")
                    user = FUser(key_name=str(profile["id"]),
                                id=str(profile["id"]),
                                name=profile["name"],
                                profile_url=profile["link"],
                                access_token=cookie["access_token"])
                    user.put()
                elif user.access_token != cookie["access_token"]:
                    user.access_token = cookie["access_token"]
                    user.put()
                self._current_user = user
        return self._current_user


class HomeHandler(BaseHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), "example.html")
    logging.debug("logging current_user"+str(self.current_user))
        args = dict(current_user=self.current_user,
                    facebook_app_id=FACEBOOK_APP_ID)
        self.response.out.write(template.render(path, args))


def main():
    util.run_wsgi_app(webapp.WSGIApplication([(r"/example", HomeHandler)]))


if __name__ == "__main__":
    main()


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Facebook Example</title>
  </head>
  <body>
    <fb:login-button autologoutlink="true"></fb:login-button>

    {% if current_user %}
      <p><a href="{{ current_user.profile_url }}"><img src="http://graph.facebook.com/{{ current_user.id }}/picture?type=square"/></a></p>
      <p>Hello, {{ current_user.name|escape }}</p>
    {% endif %}



    <div id="fb-root"></div>
    <script>
      window.fbAsyncInit = function() {
        FB.init({appId: '{{ facebook_app_id }}', status: true, cookie: true,
                 xfbml: true});
        FB.Event.subscribe('{% if current_user %}auth.logout{% else %}auth.login{% endif %}', function(response) {
          window.location.reload();
        });
      };
      (function() {
        var e = document.createElement('script');
        e.type = 'text/javascript';
        e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
        e.async = true;
        document.getElementById('fb-root').appendChild(e);
      }());
    </script>
  </body>
</html>

更新

我仍然没有获取用户对象并将HomeHandler更改为此

class HomeHandler(BaseHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), "example.html")
    logging.debug("logging current_user"+str(self.current_user))
        args = dict(current_user=self.current_user,
                    facebook_app_id=FACEBOOK_APP_ID)

    user = facebook.get_user_from_cookie(self.request.cookies, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET)

        if not user:
        logging.debug("no user")

    if user:
        graph = facebook.GraphAPI(user["access_token"])
        profile = graph.get_object("me")
        friends = graph.get_connections("me", "friends")
    logging.debug("logging profile"+str(profile))
        self.response.out.write(template.render(path, args))

2 个答案:

答案 0 :(得分:1)

Facebook切换到OAuth2.0 on October 1,2011,此代码已过时,应该可以继续使用了。

答案 1 :(得分:1)

关于@Shay Erlichmen的观察,由于facebook几天前的变化,上述代码不起作用。正如我在你原来的问题上指出的那样,有一个版本的facebook python SDK已被修改以支持新的身份验证机制 - 参见

https://gist.github.com/1190267

与旧版本不同的具体位置是get_user_from_cookie()方法。如果您仍在使用旧版本的facebook python SDK,那么应该查找fbs_APPID Cookie,找不到它并返回None - 因此永远不会为cookie分配值{ {1}}保留在方法开头指定的_current_user州。

您可以执行的一项检查是查看浏览器中的Cookie - 您应该会看到旧库中未处理的新None Cookie。