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
-~----------~----~----~----~------~----~------~--~---

Reply via email to