【问题标题】:give openid users additional information给 openid 用户额外的信息
【发布时间】:2012-06-25 05:25:53
【问题描述】:

所以我正在为 jinja2 模板平台上的 google appengine 用 python 编写一个应用程序。我已经让 OpenID 在我的网站上正常工作,它允许用户登录,我可以在右上角显示他们的电子邮件/ID。

现在我希望用户拥有自己的用户名,并能够存储一些关于他们的额外数据,例如网站访问和网站区域的某些帖子。

我知道我需要在数据库中创建一个包含用户和所有内容的表,但是使用 OpenID 执行此操作的正确方法是什么。我想在有人第一次登录时自动创建用户,但我不太确定如何有效地做到这一点。我想我可以通过在登录后将它们重定向到一个页面来管理它,该页面检查他们在数据库中的 federated_identity,如果它已经存在,它只是将它们重定向到主页,但如果不存在,它会创建一个新用户。

有没有更有效的方法,这样我就不会在每次有人登录时都查询数据库,或者这是一种相当不错的方法?

【问题讨论】:

    标签: python google-app-engine openid jinja2


    【解决方案1】:

    您是对的,您必须创建自己的用户模型并存储额外信息以及您在应用程序中拥有的任何业务逻辑。你所要做的就是存储一些独特的东西(例如federated_id)以及额外的usernamename等。

    使用 OpenID 登录后,您将检查该特定 federated_id 是否在您的数据存储中,您将返回该特定 user_db,或者使用默认值创建一个新的 user_db

    重要的是,在您的请求中,您将始终处理您自己的 user_db 实体,而不是 users.get_current_user(),因为这基本上是只读且有限的。

    这是一个完整的示例,它还演示了带有get_user() 函数的base handler class,如果用户登录,它将返回您自己的user_db 实体,否则返回None。如果用户是第一次登录,则会创建一个新的 user_db 实体,并使用一些默认值(nameusernameemailadminfederated_id):

    from google.appengine.api import users
    from google.appengine.ext import ndb
    import webapp2
    
    class User(ndb.Model):
      name = ndb.StringProperty(required=True)
      username = ndb.StringProperty(required=True)
      email = ndb.StringProperty()
      federated_id = ndb.StringProperty()
      admin = ndb.BooleanProperty()
    
    class BaseHandler(webapp2.RequestHandler):
      def get_user_db(self):
        federated_user = users.get_current_user()
        if not federated_user:
          return None
        user_db_qry = User.query(User.federated_id == federated_user.user_id())
        user_db_list = user_db_qry.fetch(1)
        #If that returns non empty list, then return the first element which is the user_db
        if user_db_list:
          return user_db_list[0]
    
        #Otherwise create a new user_db entity, with default values and return
        user_db = User(
            name=federated_user.nickname().title(),
            username=federated_user.nickname(),
            email=federated_user.email(),
            federated_id=federated_user.user_id(),
            admin=users.is_current_user_admin(),
          )
        user_db.put()
        return user_db
    
    class MainHandler(BaseHandler):
      def get(self):
        self.response.headers['Content-Type'] = 'text/html'
        if self.get_user_db():
          self.response.out.write('Hello, %s!</br>' % self.get_user_db().name)
          self.response.out.write('<a href="%s">Logout</a>' % (users.create_logout_url(self.request.uri)))
        else:
          self.response.out.write('Hello, stranger!<br>')
          self.response.out.write('<a href="%s">Login</a>' % (users.create_login_url(self.request.uri)))
    
    app = webapp2.WSGIApplication([('/', MainHandler)],
                                  debug=True)
    

    这个问题有很多不同的方法,但我认为这是一个很好的开始。

    【讨论】:

    • 好的,谢谢,今天下午我会测试一下,看看效果如何
    • 你能解释一下这行是做什么的吗:user_db_list = User.query(User.federated_id == federated_user.user_id()).fetch(1)
    • @clifgray 该行正在从您自己的模型中检索具有特定 federated_id 的用户...如果结果不是空列表,那么我们就有了赢家.. 否则我们必须创建一个实体,然后返回它..
    • @clifgray 我应该进行哪些更改以便用户可以创建新帐户而不是选择 OpenID?
    • @Sandeep 您还在寻找答案还是找到了解决方案?
    猜你喜欢
    • 2016-12-28
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 2023-03-08
    • 2022-10-23
    • 2015-06-23
    • 1970-01-01
    相关资源
    最近更新 更多