Как реализовать простые сессии для Google App Engine?

Вот очень простой класс для обработки сессий на Механизме Приложения:

"""Lightweight implementation of cookie-based sessions for Google App Engine.

Classes:
Session

"""

import os
import random
import Cookie
from google.appengine.api import memcache

_COOKIE_NAME = 'app-sid'
_COOKIE_PATH = '/'
_SESSION_EXPIRE_TIME = 180 * 60


class Session(object):

    """Cookie-based session implementation using Memcached."""

    def __init__(self):
        self.sid = None
        self.key = None
        self.session = None
        cookie_str = os.environ.get('HTTP_COOKIE', '')
        self.cookie = Cookie.SimpleCookie()
        self.cookie.load(cookie_str)
        if self.cookie.get(_COOKIE_NAME):
            self.sid = self.cookie[_COOKIE_NAME].value
            self.key = 'session-' + self.sid
            self.session = memcache.get(self.key)
        if self.session:
            self._update_memcache()
        else:
            self.sid = str(random.random())[5:] + str(random.random())[5:]
            self.key = 'session-' + self.sid
            self.session = dict()
            memcache.add(self.key, self.session, _SESSION_EXPIRE_TIME)
            self.cookie[_COOKIE_NAME] = self.sid
            self.cookie[_COOKIE_NAME]['path'] = _COOKIE_PATH
            print self.cookie

    def __len__(self):
        return len(self.session)

    def __getitem__(self, key):
        if key in self.session:
            return self.session[key]
        raise KeyError(str(key))

    def __setitem__(self, key, value):
        self.session[key] = value
        self._update_memcache()

    def __delitem__(self, key):
        if key in self.session:
            del self.session[key]
            self._update_memcache()
            return None
        raise KeyError(str(key))

    def __contains__(self, item):
        try:
            i = self.__getitem__(item)
        except KeyError:
            return False
        return True

    def _update_memcache(self):
        memcache.replace(self.key, self.session, _SESSION_EXPIRE_TIME)

Я хотел бы некоторые советы относительно того, как улучшить код для лучшей безопасности.

Примечание: В производственной версии это также сохранит копию сессии в хранилище данных.

Отметьте': Я знаю, что существует намного больше полноценных внедрений, доступных онлайн, хотя я хотел бы узнать больше об этом предмете, поэтому не отвечайте на вопрос с "использованием, которые" или "пользуются другой" библиотекой.

7
задан 7 July 2013 в 14:17
поделиться

2 ответа

Вот предложение по упрощению вашей реализации.

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

Почему бы не рандомизировать ключ сессии в хранилище данных, а затем использовать его как единственный ключ и для базы данных, и для memcache (если необходимо)? Не создаст ли это упрощение каких-либо новых проблем с безопасностью?

Вот код для создания рандомизированного ключа хранилища данных для модели Session:

# Get a random integer to use as the session's datastore ID.
# (So it can be stored in a cookie without being 'guessable'.)
random.seed();
id = None;
while None==id or Session.get_by_id( id ):
    id = random.randrange( sys.maxint );
seshKey = db.Key.from_path( 'Session', id );    
session = Session( key = seshKey );

Для получения ID из сессии (т.е. для хранения в cookie) используйте:

sid = session.key().id();

Для получения экземпляра сессии после считывания 'sid' из cookie:

session = Session.get_by_id( sid );
5
ответ дан 7 December 2019 в 12:18
поделиться

Вот несколько дополнительных мер безопасности, которые вы могли бы добавить.

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

newip = str( request.remote_addr );
if sesh.ip_addr != newip:
    logging.warn( "Session IP has changed to %s." % newip);
newua = rh.request.headers.get( 'User-Agent', None );
if sesh.agent != newua:
    logging.warn( "Session UA has changed to %s." % newua );

Также, возможно, было бы лучше запретить возобновление сеанса на неопределенный срок? Я думаю, что такие сайты, как Google, в конечном итоге попросят вас снова войти в систему, если вы попытаетесь сохранить сеанс в течение длительного времени.

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

0
ответ дан 7 December 2019 в 12:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: