Обнаружение первого входа пользователя в приложение (Google Appengine) - PullRequest
1 голос
/ 23 июня 2009

Мое приложение требует, чтобы пользователи входили в систему, используя свою учетную запись Google.

У меня есть этот набор в моем файле App.yamp:

  • url: /user/.*
    скрипт: user.py
    Логин: требуется

Теперь, когда любой пользователь пытается получить доступ к файлам в /user/secret.py, ему нужно будет пройти аутентификацию через Google, который перенаправит пользователя обратно в /user/secret.py после успешной аутентификации. Теперь проблема, с которой я сталкиваюсь, заключается в том, что когда пользователь перенаправляется обратно в приложение, я не могу быть уверен, что это первый раз, когда пользователь вошел в систему или это обычный пользователь на мой сайт, который снова вернулся от только пользователя объект, который Google передает, используя users.get_current_user ().

Поэтому мне нужно поддерживать состояние в хранилище данных, чтобы проверить, существует ли пользователь уже или нет каждый раз. Если он не существует, мне нужно создать новую запись с другими настройками приложения.

Мой вопрос: есть ли более простой способ справиться с этим? без необходимости запрашивать хранилище данных, чтобы выяснить, является ли он новым пользователем или обычным?

Ответы [ 4 ]

2 голосов
/ 23 июня 2009

Нет, Google не отслеживает, заходил ли пользователь в ваше приложение раньше. Поскольку, по-видимому, вам нужно хранить какое-то состояние против пользователя, самый простой способ - попытаться получить запись пользователя из хранилища данных. Если у них его нет, вы можете отправить их на экран регистрации, чтобы собрать эту информацию. Вы можете использовать memcache для кэширования информации о пользователе и избежания дополнительных обращений к хранилищу данных.

2 голосов
/ 23 июня 2009

Я склонен использовать свой собственный пользователь и управление сессиями

Для моих веб-обработчиков я прикреплю декоратор, называемый сеансом, и один, называемый авторизацией. Декоратор сеанса будет прикреплять сеанс к каждому запросу, а декоратор авторизации будет гарантировать, что пользователь авторизован

(Предупреждение: декоратор авторизации относится к тому, как я разрабатываю свои приложения - имя пользователя является первым параметром в большинстве запросов)

Так, например, веб-обработчик может выглядеть так:

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
1 голос
/ 18 апреля 2010

Я согласен, что управление вашими аутентифицированными пользователями - лучший способ решения этой проблемы. Очевидно, что в зависимости от области вашего приложения, но, по крайней мере, класс 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)
...

и при входе в систему: проверьте, есть ли они в списке; если нет, вы добавляете их в список, ставите () и выполняете все, что вам нужно, для начинающих пользователей. Если вы найдете их там, то делайте другие вещи.

1 голос
/ 23 июня 2009

Разве вы не можете просто установить Cookie при первом входе пользователя в систему и проверить это? Если они новый пользователь, его там не будет, но если он будет старым пользователем, он будет. Это не на 100% точно, так как некоторые пользователи могут очистить свои куки, но это может быть сделано в зависимости от того, чего вы хотите достичь.

Если вы используете Django в своем приложении управлять Cookies довольно просто .

...