I've gone with a different approach that currently achieves similar results, that's now available in the trunk. A new variable, last_activity_update has been added. It's the amount of seconds that needs to pass before that field needs to be updated by doing a put(). It defaults to 60 seconds, which of course is longer than the duration before a put is required to update the session token with the default settings.
This will allow developers who wish to lengthen their session_token_ttl to a larger interval to still get their last_activity update in, useful for session timing. It too is customizable so for developers who have no use for this field can set it to a large enough number to be irrelevant. I'm trying to flush out an idea I have to limit the amount of writes for the token even further, but am still researching it. If I figure it out I will get it in and do another release. Otherwise I will release what's there now. Before any release I want to go over the refactoring you did as it does look more efficient than what I currently have, thanks. On Jan 22, 6:31 pm, jeremy <jeremy.a...@gmail.com> wrote: > Ok. I actually modified Session.__init__ locally to do the > last_activity on sid rotation (i also refactored it a bit to reduce > repeated code blocks). Regarding google.com's SID cookie - i'm not > seeing the sid update within minutes. I'm not sure why yours rotates > so quickly, but it's something entirely configurable in your code so > it shouldn't matter. Anyway, here's my version of Session.__init__ : > > def __init__(self, cookie_path=DEFAULT_COOKIE_PATH, > cookie_name=COOKIE_NAME, > session_expire_time=SESSION_EXPIRE_TIME, > clean_check_percent=CLEAN_CHECK_PERCENT, > integrate_flash=INTEGRATE_FLASH, check_ip=CHECK_IP, > check_user_agent=CHECK_USER_AGENT, > set_cookie_expires=SET_COOKIE_EXPIRES, > session_token_ttl=SESSION_TOKEN_TTL): > """ > Initializer > > Args: > cookie_name: The name for the session cookie stored in the > browser. > session_expire_time: The amount of time between requests > before the > session expires. > clean_check_percent: The percentage of requests the will > fire off a > cleaning routine that deletes stale session data. > integrate_flash: If appengine-utilities flash utility should > be > integrated into the session object. > check_ip: If browser IP should be used for session > validation > check_user_agent: If the browser user agent should be used > for > sessoin validation. > set_cookie_expires: True adds an expires field to the cookie > so > it saves even if the browser is closed. > session_token_ttl: Number of sessions a session token is > valid > for before it should be regenerated. > """ > > self.cookie_path = cookie_path > self.cookie_name = cookie_name > self.session_expire_time = session_expire_time > self.clean_check_percent = clean_check_percent > self.integrate_flash = integrate_flash > self.check_user_agent = check_user_agent > self.check_ip = check_ip > self.set_cookie_expires = set_cookie_expires > self.session_token_ttl = session_token_ttl > > # make sure the page is not cached in the browser > self.no_cache_headers() > """ > Check the cookie and, if necessary, create a new one. > """ > self.cache = {} > self.sid = None > string_cookie = os.environ.get('HTTP_COOKIE', '') > self.cookie = Cookie.SimpleCookie() > self.output_cookie = Cookie.SimpleCookie() > self.cookie.load(string_cookie) > > dirty = False > > # check for existing cookie > if self.cookie.get(cookie_name): > self.sid = self.cookie[cookie_name].value > self.session = self._get_session() # will return None if > sid expired > else: > self.sid = self.new_sid() > self.session = None > > if self.session is None: > # start a new session if there is None. > self.sid = self.new_sid() > self.session = _AppEngineUtilities_Session() > if 'HTTP_USER_AGENT' in os.environ: > self.session.ua = os.environ['HTTP_USER_AGENT'] > else: > self.session.ua = None > if 'REMOTE_ADDR' in os.environ: > self.session.ip = os.environ['REMOTE_ADDR'] > else: > self.session.ip = None > self.session.sid = [self.sid] > dirty = True > else: > # check the age of the token to determine if a new one > # is required > duration = datetime.timedelta > (seconds=self.session_token_ttl) > session_age_limit = datetime.datetime.now() - duration > if self.session.last_activity < session_age_limit: > self.sid = self.new_sid() > if len(self.session.sid) > 2: > self.session.sid.remove(self.session.sid[0]) > self.session.sid.append(self.sid) > dirty = True > else: > self.sid = self.session.sid[-1] > > self.output_cookie[cookie_name] = self.sid > self.output_cookie[cookie_name]['path'] = cookie_path > if set_cookie_expires: > self.output_cookie[cookie_name]['expires'] = > self.session_expire_time > > self.cache['sid'] = pickle.dumps(self.sid) > > if dirty: > self.session.put() > > #self.cookie.output() > print self.output_cookie.output() > > # fire up a Flash object if integration is enabled > if self.integrate_flash: > import flash > self.flash = flash.Flash(cookie=self.cookie) > > # randomly delete old stale sessions in the datastore (see > # CLEAN_CHECK_PERCENT variable) > if random.randint(1, 100) < CLEAN_CHECK_PERCENT: > self._clean_old_sessions() > > On Jan 22, 4:38 pm, "bowman.jos...@gmail.com" > > <bowman.jos...@gmail.com> wrote: > > I think it's a case of it's been that way for so long I haven't > > realized I need to change it. The put on every write to update the > > last activity, I mean. I'll look into modifying it so that it only > > writes when the session token changes. > > > As for google though, every time I load up my igoogle page, I have > > cookie called SID for thewww.google.comthatchanges each page view. > > This is really as it should be for real security, as even the 15 > > second window I have configured by default it more that large enough > > for someone to write a script very quickly to sniff and grab the > > cookie to be used to hijack the session. > > > Modifying the last_activity to update less frequently is a good idea, > > I will try to get that in soon. > > > On Jan 22, 2:08 pm, jeremy <jeremy.a...@gmail.com> wrote: > > > > Bowman - I think my issue with gaeutilities may largely be that the > > > default settings seem excessive. Looking at the cookies google.com > > > hands its visitors, their SID cookie lasts a good decade and seems to > > > rotate every few hours, not seconds. So at the moment i'm thinking > > > I'll see if changing the default satisfies me. > > > > Also, at the moment there's a datastore put() on every session-using > > > request to (at a minimum) update the last activity time stamp. But if > > > my SESSION_TOKEN_TTL is something like 1 hour, then actually i only > > > need to update the last activity time stamp if the last timestamp was > > > more than an hour ago. That would significantly reduce the amount of > > > datastore writes, no? > > > > re: "I'm just trying to figure out the value in the signed cookie > > > approach, because if I can figure out a way for it to make sense I > > > would consider moving gaeutilities to that approach. ": > > > > Do you mean storing all session data in the clients cookie and using a > > > signature to authenticate it? That approach makes me nervous, although > > > I can imagine it's actually quite effective. You just store the > > > session data in plain text but then also include a signature = SHA1 > > > (session_data + secret_key_only_the_server_knows). That way the server > > > can confirm it was the one who committed the values (and not the > > > client messing with their own cookies). > > > > On Jan 21, 8:33 pm, "bowman.jos...@gmail.com" > > > > <bowman.jos...@gmail.com> wrote: > > > > Does beaker store all session information as cookies? > > > > > I'm just trying to figure out the value in the signed cookie approach, > > > > because if I can figure out a way for it to make sense I would > > > > consider moving gaeutilities to that approach. > > > > > gaeutilities stores only a temporary session token in the browser > > > > cookie store, all information is stored server side for security. > > > > Since I only have the one cookie, which is basically an id to find the > > > > session server side with, I don't see a way for this approach to keep > > > > a session from being hijacked. As in the end the 'hash-value' string > > > > could be hijacked and reused by another browser. > > > > > The performance issue with gaeutililites, and why Jeremy is looking > > > > for options, is the approach I've taken to securing the session id > > > > requires frequent put() operations. I've seen some other blogs who've > > > > mentioned this is a performance bottleneck for gae, but I haven't been > > > > able to come up with another approach that will not sacrifice > > > > reliability or performance. Basically I rotate the session id in the > > > > cookie every 5 seconds (this length is configurable). I store the > > > > current plus previous 2 tokens in a ListProperty in order to manage > > > > sites using AJAX type functionality. A session token is generally good > > > > for 15 seconds with this approach. Longer if there are not interim > > > > requests generating new tokens, as a new token is only generated when > > > > the 5 second TTL is hit. So you come back 2 minutes later, and the > > > > session token is still valid for that request, just regenerated on the > > > > request. As you can imagine, this is a lot of put operations for each > > > > session. > > > > > I deemed just using memcache to not be a viable alternative because > > > > it's documented that it's a volatile storage, it can be cleared at any > > > > time. I do use memcache for speeding up reads to the session data, > > > > limiting read access to the datastore. > > > > > I'm definitely open to suggestions for a method to do this without all > > > > the puts. The key being the reliability and security are more > > > > important than performance. In the end it's cheaper to pay for the CPU > > > > usage than the risks by allowing users to have their sessions easily > > > > hijacked, depending on the application, or having sessions randomly > > > > lost due to the storage medium not being permanent enough. > > > > > On Jan 21, 6:27 pm, jeremy > > ... > > read more » --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google App Engine" group. To post to this group, send email to google-appengine@googlegroups.com To unsubscribe from this group, send email to google-appengine+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en -~----------~----~----~----~------~----~------~--~---