1

我的应用程序要求用户使用他们的谷歌帐户登录。

我在我的 App.yamp 文件中有这个设置:

  • 网址:/user/.*
    脚本:user.py
    登录:必需

现在,当任何用户尝试访问 /user/secret.py 下的文件时,他将需要通过 google 进行身份验证,这将在成功身份验证后将用户重定向回 /user/secret.py。现在我面临的问题是当用户被重定向回应用程序时,我无法确定这是用户第一次登录还是我网站的普通用户再次从用户那里回来google 使用 users.get_current_user() 传递的对象。

因此,我需要在数据存储中维护状态以检查用户是否已经存在。如果他不存在,我需要使用其他应用程序特定设置创建一个新条目。

我的问题是:有没有更简单的方法来处理这个问题?无需查询数据存储来确定这是第一次使用还是普通用户?

4

4 回答 4

2

我倾向于使用自己的用户和会话管理

对于我的 web 处理程序,我将附加一个名为 session 的装饰器和一个名为 authorize 的装饰器。会话装饰器将会话附加到每个请求,授权装饰器将确保用户被授权

(请注意,授权装饰器特定于我如何开发我的应用程序 - 用户名是大多数请求中的第一个参数)

例如,一个 web 处理程序可能看起来像:

class UserProfile(webapp.RequestHandler):
  @session
  @authorize
  def get(self, user):
     # Do some funky stuff
     # The session is attached to the self object.
     someObjectAttachedToSession = self.SessionObj.SomeStuff
     self.response.out.write("hello %s" % user)

在上面的代码中,会话装饰器根据请求中存在的 cookie 附加了一些我需要的会话内容。授权标头将确保用户只能在会话正确的情况下访问该页面。

装饰器代码如下:

import functools
from model import Session
import logging

def authorize(redirectTo = "/"):
    def factory(method):
        'Ensures that when an auth cookie is presented to the request that is is valid'
        @functools.wraps(method)
        def wrapper(self, *args, **kwargs):

            #Get the session parameters
            auth_id = self.request.cookies.get('auth_id', '')
            session_id = self.request.cookies.get('session_id', '')

            #Check the db for the session
            session = Session.GetSession(session_id, auth_id)           

            if session is None:
                self.redirect(redirectTo)
                return
            else:
                if session.settings is None:
                    self.redirect(redirectTo)
                    return

                username = session.settings.key().name()

                if len(args) > 0:               
                    if username != args[0]:
                        # The user is allowed to view this page.
                        self.redirect(redirectTo)
                        return

            result = method(self, *args, **kwargs)

            return result
        return wrapper
    return factory

def session(method):
    'Ensures that the sessions object (if it exists) is attached to the request.'
    @functools.wraps(method)
    def wrapper(self, *args, **kwargs):

        #Get the session parameters
        auth_id = self.request.cookies.get('auth_id', '')
        session_id = self.request.cookies.get('session_id', '')

        #Check the db for the session
        session = Session.GetSession(session_id, auth_id)           

        if session is None:
            session = Session()
            session.session_id = Session.MakeId()
            session.auth_token = Session.MakeId()
            session.put()

        # Attach the session to the method
        self.SessionObj = session           

        #Call the handler.          
        result = method(self, *args, **kwargs)

        self.response.headers.add_header('Set-Cookie', 'auth_id=%s; path=/; HttpOnly' % str(session.auth_token))
        self.response.headers.add_header('Set-Cookie', 'session_id=%s; path=/; HttpOnly' % str(session.session_id))

        return result
    return wrapper

def redirect(method, redirect = "/user/"):
    'When a known user is logged in redirect them to their home page'
    @functools.wraps(method)
    def wrapper(self, *args, **kwargs):
        try:    
            if self.SessionObj is not None:
                if self.SessionObj.settings is not None:
                    # Check that the session is correct
                    username = self.SessionObj.settings.key().name()

                    self.redirect(redirect + username)
                    return
        except:
            pass
        return method(self, *args, **kwargs)
    return wrapper
于 2009-06-23T15:34:29.173 回答
2

不,Google 不会跟踪用户之前是否登录过您的应用。由于您可能需要针对用户存储某种状态,因此最简单的方法是尝试从数据存储中检索用户的记录。如果他们没有,您可以将他们发送到注册屏幕以收集此信息。您可以使用 memcache 来缓存用户的信息并避免额外的数据存储往返。

于 2009-06-23T11:59:51.713 回答
1

你不能在用户第一次登录时设置一个 Cookie 并检查吗?如果他们是新用户,它将不存在,但如果他们是老用户,它将存在。这不是 100% 准确的,因为一些用户可能会清除他们的 cookie,但它可能会根据您想要实现的目标来实现。

如果您在应用程序中使用 Django,管理 Cookie 非常简单

于 2009-06-23T10:42:59.153 回答
1

我同意管理您自己的经过身份验证的用户是解决此问题的最佳方法。显然取决于您的应用程序范围,但至少是一个 AuthUser(Model) 类,其中包含使用您的帐户登录的用户的 UserProperty。

...
class AuthUser(db.Model):
  user = UserProperty(required=True)
...

然后当用户登录时

...
user = users.get_current_user()
user_exists = AuthUser.gql('where user = :1', user) # or easy check db.GqlQuery("select __key__ from AuthUser where user = :1", user)
if user_exists:
  # do user has been before stuff
else:
  # do first time user stuff
...

或者,一个超级简单的方法是为您的站点创建一个具有 ListProperty(users.User) 的模型,然后您可以轻松地检查列表以查看用户之前是否进入过您的应用程序。

...
class SiteStuff(db.Model):
  auth_users = ListProperty(users.User)
...

当他们登录时:检查他们是否在列表中;如果没有,您将它们添加到列表中,put() 并为初次使用的用户做任何您需要做的事情。如果你在那里找到它们,然后做其他的事情。

于 2010-04-18T06:40:17.763 回答