小能豆

为 openid 用户提供更多信息

py

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

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

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

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


阅读 14

收藏
2024-11-14

共1个答案

小能豆

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

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

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

下面是一个完整的示例,它还演示了一个基本处理程序类,该类具有函数,如果用户已登录,则get_user()返回您自己的实体,否则返回。 如果用户是第一次登录,则会创建一个新的 user_db 实体,其中包含一些默认值(,,,,):user_db``None``name``username``email``admin``federated_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)

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

2024-11-14