Re: [OT-ish] Session refresh philosophy
> > You've addressed the issue of someone submitting a form with altered fields > to attack the server, and pointed out some more advantages, but I don't > think you've addressed the issue of protecting the "hidden" cleartext data > from others on the client side. True. But to tackle these concerns, SSL looks like a better approach to me. If the client doesn't do any math/crypto/secret stuff at all, an attacker that is on the same subnet can both spy on secrets (egress passwords or private data, ingress session IDs or cookies) and take over sessions (just by changing IPs - no need to even hijack TCP connections since they are short-lived in HTTP) - and then there is nothing that the victim could do that the attacker cannot. The point is, secrets pass over the wire in the clear at a moment or another, so encrypting them for all transfers but the first one only earns a marginal amount of security. This is not to say I don't enjoy using the various state storage mechanisms described in the thread. They are highly useful but I think that the encryption part of them only addresses problems on the server side and are useless under certain forms of site design. -- Dominique QUATRAVAUX Ingénieur développeur sénior 01 44 42 00 35 IDEALX
RE: [OT-ish] Session refresh philosophy
Drew Taylor [mailto:[EMAIL PROTECTED]] wrote: > I just looked at CGI::EncryptForm and David's module. The thing I like > right off the bat about C:EF is that you pass a href to encrypt() and get > back a href from decypt(). Perhaps I missed something, but FormContainer > takes a string, not a data structure. I prefer the simplicity of just > worrying about a structure, and not having to worry about converting it to > a string. My module, FormContainer, takes arbitrary data structures like hash references too. You probably didn't see this because I used my own serializer module called FreezeThawLite instead of Storable. The lack of documentation of my module may have also been a problem. :-) I mentioned that a trivial rewrite to use Storable would be required when I attached the code. Simply replace FreezeThawLight::freeze with Storable::freeze and FreezeThawLight::thaw with Storable::thaw. :-) I agree with you that having to manually serialize session data to a string would be a real pain! > That said, I like the approach that the two modules use. One just goes an > extra step to guarantee data security. While looking for full-time > employment, I've been doing some freelance work, which basically is small > CGI apps. C:EF looks like it would make my life much easier by ensuring > consistent state w/ small effort on my part, and take care of any security > precautions as well. Combine that w/ CGI::Application (after I add TT2 > support :-) ), and my life as a freelance CGI guy just got a whole lot easier. See my last message about the security comparisons. > Thank you to everyone who contributed to this thread. I've gotten all kinds > of neat ideas I'll use in future projects! Good stuff. David
RE: [OT-ish] Session refresh philosophy
[EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] wrote: > I can see how your approach adds functionality by performing as expected if > the user uses the Back button or opens the app. in more than one browser > window. The usual objection I've heard to using form fields is the security > risk of people changing hidden fields in ways unforseen before submitting > the form back, or of other people finding confidential data hidden in form > fields if the user walks away and leaves their browser open, or the web > page info gets hijacked somehow. Does your module address this, or is this > yet another tradeoff between security and functionality/convenience? My module addresses the first concern of an attacker changing the data in the hidden fields. On encoding, I hash together the encoded data and a secret to get a security hash. On decoding, I perform the same hashing and make sure it matches. Without the secret data no one can generate a security hash for modified data. My module does not address encryption. It would be trivial to add. It wasn't a concern with my application. By note of comparison, it looks like CGI::EncryptForm addresses both the encryption and non-user-modifiable concerns for the hidden data. David
RE: [OT-ish] Session refresh philosophy
Perrin Harkins [mailto:[EMAIL PROTECTED]] wrote: > Okay, I only looked at it briefly and thought it stored the data on the > client. Your module is actually more like CGI::EncryptForm I think, but > yours may make things a bit more transparent. Maybe you should polish it up > for CPAN. I looked at CGI::EncryptForm. It is used to store data on the client. The main difference between it and my module is that: (a) it encrypts the data, while I only prevent users from modifying the data, and (b) it stores the data in one field, while I store in multiple fields to make double sure that I don't hit any length restrictions. > I'm well aware of the page-state vs. browser-state problem. I was recently > bitten by it again when some consultants built a web app for my company that > puts the search results in a session keyed on a cookie. As soon as the user > opens two windows, it's absolute mayhem. I wasn't exactly what to call it and if people would recognize it by name, so I started writing a short description which just grew. :-) David
Re: [OT-ish] Session refresh philosophy
Rob Nagler wrote: > [EMAIL PROTECTED] writes: > > Looking at CGI::EncryptForm that Perrin mentioned, it appears that that > > module would address this concern by storing client-side in a single > > encrypted string that gets put in one hidden form variable. That also > > avoids having to verify more than once. > > It is always good to validate the data even if it was encrypted. It > is also generally a good idea not to give the user any secrets, even > if they are encrypted. In other words, avoid trusting the user. > > [EMAIL PROTECTED] writes: > > No, this just means that input must be validated once again when the > > last «really, really sure ?» button is depressed. Conceptually, this > > divides the pages of your site into two categories (not unlike the > > view vs. controller distinction in Model-View-Controller paradigm for > > GUIs): those that just interact with the user and do the navigation, > > and those that actually have side effects such as writing data into your > > database, sending e-mails, placing orders etc. > > It is MVC. However, instead of thinking of pages, I like to think in > terms of tasks. The same task that renders the form also validates > and executes it. In the case of execution, the result is a redirect > described by the site's state machine. A form in our world has four > states: execute_empty (fill in defaults), execute_ok, execute_other > (e.g., cancel or sub form), and execute_unwind (coming back from a sub > form). All of these paths go through the same task. please take this as interested and not critical. i was viewing the source: http://petshop.bivio.biz/src?s=View.items and i noticed these lines: - snip ])->put( cellpadding => 2, cellspacing => 2, ), - snip - this looks like the presentation layer peeking through. the petshop site is obviously a demo, and therefore does not have the polished look of a professional site, which is very understandable. what i wonder is, could a professional web design team make a polished website without involving the programmers? what happens when a cell padding of 3 is more desirable for the design? it seems to me, that in all of the technologies i have looked at thus far, that attempt to separate the presentation layer from the model/view, the precision and flexibility needed to graphically communicate to the user is more difficult that the standard pagedesign approaches (dreamweaver and a little embperl or other embedded language thrown into the mix) . phrased another way, how does bivio or other mvc technology, let web artists design sites as beautiful as http://www.marthastewart.com or the even more beautiful http://www.genwax.com (cheap plug)? -- ___cliff [EMAIL PROTECTED]http://www.genwax.com/
Re: [OT-ish] Session refresh philosophy
[EMAIL PROTECTED] writes: > Looking at CGI::EncryptForm that Perrin mentioned, it appears that that > module would address this concern by storing client-side in a single > encrypted string that gets put in one hidden form variable. That also > avoids having to verify more than once. It is always good to validate the data even if it was encrypted. It is also generally a good idea not to give the user any secrets, even if they are encrypted. In other words, avoid trusting the user. [EMAIL PROTECTED] writes: > No, this just means that input must be validated once again when the > last «really, really sure ?» button is depressed. Conceptually, this > divides the pages of your site into two categories (not unlike the > view vs. controller distinction in Model-View-Controller paradigm for > GUIs): those that just interact with the user and do the navigation, > and those that actually have side effects such as writing data into your > database, sending e-mails, placing orders etc. It is MVC. However, instead of thinking of pages, I like to think in terms of tasks. The same task that renders the form also validates and executes it. In the case of execution, the result is a redirect described by the site's state machine. A form in our world has four states: execute_empty (fill in defaults), execute_ok, execute_other (e.g., cancel or sub form), and execute_unwind (coming back from a sub form). All of these paths go through the same task. Rob
Re: [OT-ish] Session refresh philosophy
I just looked at CGI::EncryptForm and David's module. The thing I like right off the bat about C:EF is that you pass a href to encrypt() and get back a href from decypt(). Perhaps I missed something, but FormContainer takes a string, not a data structure. I prefer the simplicity of just worrying about a structure, and not having to worry about converting it to a string. That said, I like the approach that the two modules use. One just goes an extra step to guarantee data security. While looking for full-time employment, I've been doing some freelance work, which basically is small CGI apps. C:EF looks like it would make my life much easier by ensuring consistent state w/ small effort on my part, and take care of any security precautions as well. Combine that w/ CGI::Application (after I add TT2 support :-) ), and my life as a freelance CGI guy just got a whole lot easier. Thank you to everyone who contributed to this thread. I've gotten all kinds of neat ideas I'll use in future projects! Drew At 10:19 AM 2/20/2002 -0500, Perrin Harkins wrote: > > When I used CGI::SecureState it gave the client a non-versioning (more on > > that later) key and stored the state information in the filesystem. > >Okay, I only looked at it briefly and thought it stored the data on the >client. Your module is actually more like CGI::EncryptForm I think, but >yours may make things a bit more transparent. Maybe you should polish it up >for CPAN. > >I'm well aware of the page-state vs. browser-state problem. I was recently >bitten by it again when some consultants built a web app for my company that >puts the search results in a session keyed on a cookie. As soon as the user >opens two windows, it's absolute mayhem. > >- Perrin Drew Taylor JA[P|m_p|SQL]H http://www.drewtaylor.com/ Just Another Perl|mod_perl|SQL Hacker mailto:[EMAIL PROTECTED] *** God bless America! ***
Re: [OT-ish] Session refresh philosophy
You've addressed the issue of someone submitting a form with altered fields to attack the server, and pointed out some more advantages, but I don't think you've addressed the issue of protecting the "hidden" cleartext data from others on the client side. I guess that's a matter of how paranoid you think you need to be, and how confidential is the data you're storing. Looking at CGI::EncryptForm that Perrin mentioned, it appears that that module would address this concern by storing client-side in a single encrypted string that gets put in one hidden form variable. That also avoids having to verify more than once. Looks like it might worth be taking another look at this approach next time I start a new project. Wes [EMAIL PROTECTED] on 02/20/2002 11:48:28 AM Please respond to [EMAIL PROTECTED] To: mod_perl Mailing List <[EMAIL PROTECTED]> cc: Subject: Re: [OT-ish] Session refresh philosophy > The usual objection I've heard to using form fields is the security > risk of people changing hidden fields in ways unforseen before submitting > the form back, or of other people finding confidential data hidden in form > fields if the user walks away and leaves their browser open, or the web > page info gets hijacked somehow. Does your module address this, or is this > yet another tradeoff between security and functionality/convenience? No, this just means that input must be validated once again when the last «really, really sure ?» button is depressed. Conceptually, this divides the pages of your site into two categories (not unlike the view vs. controller distinction in Model-View-Controller paradigm for GUIs): those that just interact with the user and do the navigation, and those that actually have side effects such as writing data into your database, sending e-mails, placing orders etc. Both page types may have form input validation code on the server side, but in the first case this is just convenience for the user (warn early and don't say "woops" after 9 pages and 10 minutes of typing). The latter MUST have validation for security to hold (even if this means validating twice). This way, changing hidden fields gains an attacker nothing, since he will be blocked at the final submit anyway. Doing things this way also has other advantages e.g. interfacing: one can write automatisms with "wget" or LWP::UserAgent to trigger actions in the database without any further programming needed on the server side. -- Dominique QUATRAVAUX Ingénieur développeur sénior 01 44 42 00 35 IDEALX
Re: [OT-ish] Session refresh philosophy
> The usual objection I've heard to using form fields is the security > risk of people changing hidden fields in ways unforseen before submitting > the form back, or of other people finding confidential data hidden in form > fields if the user walks away and leaves their browser open, or the web > page info gets hijacked somehow. Does your module address this, or is this > yet another tradeoff between security and functionality/convenience? No, this just means that input must be validated once again when the last «really, really sure ?» button is depressed. Conceptually, this divides the pages of your site into two categories (not unlike the view vs. controller distinction in Model-View-Controller paradigm for GUIs): those that just interact with the user and do the navigation, and those that actually have side effects such as writing data into your database, sending e-mails, placing orders etc. Both page types may have form input validation code on the server side, but in the first case this is just convenience for the user (warn early and don't say "woops" after 9 pages and 10 minutes of typing). The latter MUST have validation for security to hold (even if this means validating twice). This way, changing hidden fields gains an attacker nothing, since he will be blocked at the final submit anyway. Doing things this way also has other advantages e.g. interfacing: one can write automatisms with "wget" or LWP::UserAgent to trigger actions in the database without any further programming needed on the server side. -- Dominique QUATRAVAUX Ingénieur développeur sénior 01 44 42 00 35 IDEALX
RE: [OT-ish] Session refresh philosophy
I can see how your approach adds functionality by performing as expected if the user uses the Back button or opens the app. in more than one browser window. The usual objection I've heard to using form fields is the security risk of people changing hidden fields in ways unforseen before submitting the form back, or of other people finding confidential data hidden in form fields if the user walks away and leaves their browser open, or the web page info gets hijacked somehow. Does your module address this, or is this yet another tradeoff between security and functionality/convenience? Wes Sheldahl "David Harris" <[EMAIL PROTECTED]> on 02/20/2002 09:50:11 AM To: "Perrin Harkins" <[EMAIL PROTECTED]>, "Drew Taylor" <[EMAIL PROTECTED]>, "mod_perl Mailing List" <[EMAIL PROTECTED]> cc: Subject: RE: [OT-ish] Session refresh philosophy Perrin Harkins [mailto:[EMAIL PROTECTED]] wrote: > > I built and use a module that encodes a session hash into a > > number of hidden fields with a security MD5 sum. > > Sounds a lot like CGI::SecureState. Have you ever looked at it? My module doesn't need to store any information in a database or in the filesystem. The entire state is given to the client in hidden form fields, and is passed back to the server on the next request. In addition, CGI::SecureState does not tie the state information to the *page*. With my module (or any method that stores the *data* in a hidden form field, not just a non-versioning key), state information is tied to the page. Let me explain:
Re: [OT-ish] Session refresh philosophy
> When I used CGI::SecureState it gave the client a non-versioning (more on > that later) key and stored the state information in the filesystem. Okay, I only looked at it briefly and thought it stored the data on the client. Your module is actually more like CGI::EncryptForm I think, but yours may make things a bit more transparent. Maybe you should polish it up for CPAN. I'm well aware of the page-state vs. browser-state problem. I was recently bitten by it again when some consultants built a web app for my company that puts the search results in a session keyed on a cookie. As soon as the user opens two windows, it's absolute mayhem. - Perrin
RE: [OT-ish] Session refresh philosophy
Hans Juergen von Lengerke [mailto:[EMAIL PROTECTED]] wrote: > David Harris <[EMAIL PROTECTED]> on Feb 19, 2002: > > The encoded information is [...] split into reasonable length hidden > > fields. > > Why not put everything in one field? Are there restrictions? Does it > make a difference when using POST? The POST encoding dose not have a limit on data length. Heck, people use tags with huge amounts of content all the time. However, I didn't feel comfortable assuming that the HTML parser used by the browser could easily parse a potentially 20kb attribute. Basically, I didn't want to make my production application a stress-test for my user's browsers. :-) It was easy to break the data up into multiple hidden fields, because Base64 encoding breaks the data into multiple lines by default. I simply encoded each line in one hidden field. I would *NOT* use my module with a GET form if you expect any size of data. I've seen the query string get truncated at some arbitrary size limit. David
Re: [OT-ish] Session refresh philosophy
Hans Juergen von Lengerke writes: > Why not put everything in one field? Are there restrictions? Does it > make a difference when using POST? That's what we do. There doesn't appear to be a restriction with POST. For while, we were encoding entire forms in URLs, but the limits got to us for really large forms. Rob
RE: [OT-ish] Session refresh philosophy
Perrin Harkins [mailto:[EMAIL PROTECTED]] wrote: > > I built and use a module that encodes a session hash into a > > number of hidden fields with a security MD5 sum. > > Sounds a lot like CGI::SecureState. Have you ever looked at it? I just installed and played with CGI::SecureState (using the example in the POD) and it is totally different than my module. When I used CGI::SecureState it gave the client a non-versioning (more on that later) key and stored the state information in the filesystem. My module doesn't need to store any information in a database or in the filesystem. The entire state is given to the client in hidden form fields, and is passed back to the server on the next request. In addition, CGI::SecureState does not tie the state information to the *page*. With my module (or any method that stores the *data* in a hidden form field, not just a non-versioning key), state information is tied to the page. Let me explain: Imagine a multi-step order process where the user works through pages A, B, C, and D, (which contain forms) then uses the back button to go back to page B, changes the form values, and submits the form. With CGI::SecureState, page C will receive the state information stored by page D (that was intended for use by page E, we presume), instead of the state originally stored by page B (that was intended for page C). This is because all the pages share the same key, and old "versions" of the state are overwritten by the new "versions" and no longer available. When the back button is hit, a newer version of state may be used where an older version was intended. With my module, page C always gets the state information stored for it by page B, since the state is stored in hidden form fields in page B. The browser is actually storing the state and will always submit that same state to page C. (I have mentioned that CGI::SecureState uses a non-versioning key a few times. A way to make CGI::SecureState tie the state information to the actual page would be to change the key whenever the state changed, thus creating a versioning key. The key could be a hash of the state itself. This potentially means that a huge number of versions of the state would have to be stored on disk. I think this method would only be helpful if the state is large and it's not acceptable to pass it back and forth between the client.) In addition, CGI::SecureState gets fuddled if the user opens a new window (something I do often) and then starts performing different operations in each window using the same state key! It has no way of knowing a new windows exists and generating a new key. If you just store a customer id, customer name, and other rarely changing information in the state, these concerns may not matter to you. If you break a long form or order process into multiple pages, gathering new information on each page and storing it in the state so that you can process the order at the end, then this is a likely problem. David
Re: [OT-ish] Session refresh philosophy
David Harris <[EMAIL PROTECTED]> on Feb 19, 2002: > The encoded information is [...] split into reasonable length hidden > fields. Why not put everything in one field? Are there restrictions? Does it make a difference when using POST? Hans
Re: [OT-ish] Session refresh philosophy
> I built and use a module that encodes a session hash into a number of hidden > fields with a security MD5 sum. Sounds a lot like CGI::SecureState. Have you ever looked at it? - Perrin
RE: [OT-ish] Session refresh philosophy
David Harris [[EMAIL PROTECTED]] wrote: [snip] > I've attached some code. To use the code, you'll have to replace the > module FreezeThawLite with Storable. Also, beware the \r\n newlines. > (I pulled this out of CVS on my windows desktop.) I forgot to actually attach the code David package Fusion::FormContainer; use strict; use Digest::MD5 (); use MIME::Base64 (); use FreezeThawLight (); use Compress::Zlib (); use Carp; # this respresents a securty hole if we open-source this module.. the securtiy string # needs to be passed as confguration at that point somehow. sub _create_security_string { my $string = shift; my $secret =add($string); $ctx->add($secret); return $ctx->hexdigest; } sub encode { my $info = shift; my $prefix = shift; my $string = MIME::Base64::encode(Compress::Zlib::compress(FreezeThawLight::freeze($info))); $string =~ s/\n$//; my @array; push @array, ("${prefix}_fc_security", _create_security_string($string)); my $part_number = 0; foreach my $part ( split "\n", $string ) { my $part_number_string = sprintf("%.3d", $part_number); push @array, ("${prefix}_fc_part$part_number_string", $part); $part_number++; } if ( wantarray ) { return @array; } else { my $html; while ( @array ) { my $name = shift(@array); my $value = shift(@array); $html .= < EOT } return $html; } } sub decode { my $apr = shift; my $prefix = shift; my $security = $apr->param("${prefix}_fc_security"); my @string_parts; my $part_number = 0; while ( 1 ) { my $part_number_string = sprintf("%.3d", $part_number); my $part = $apr->param("${prefix}_fc_part$part_number_string"); last if ( $part eq "" ); push @string_parts, $part; $part_number++; } my $string = join "\n", @string_parts; croak "tampered or malformed FormContainer: securty string and string don't match" if ( _create_security_string($string) ne $security ); return FreezeThawLight::thaw(Compress::Zlib::uncompress(MIME::Base64::decode($string))); } 1;
RE: [OT-ish] Session refresh philosophy
Drew Taylor [mailto:[EMAIL PROTECTED]]: > And that is what I am doing for a small project I'm working on now. In my > case, I'm not sure about the capabilities of the remote server, and I know > for sure that I don't have a database available, so session information is > saved via hidden form fields. It's primitive, but was actually a bit of a > challenge to make sure a (unused) hidden field and a visible form element > don't appear in the same . Not my first choice, but it definitely works. I built and use a module that encodes a session hash into a number of hidden fields with a security MD5 sum. The encoded information is serialized, gzipped, Base64 encoded, and then split into reasonable length hidden fields. It looks like this: This way, you don't have to worry about creating hidden form fields in your templates for every variable you need to encode. In your perl, simply call the session encode and decode methods. You are also assured that nobody messed with the data. You can easily "pass" arbitrarily complex session information from one page to another without using a database, and the session info is truly tied to the *page*. Use of the back button, therefore, doesn't break anything. I've attached some code. To use the code, you'll have to replace the module FreezeThawLite with Storable. Also, beware the \r\n newlines. (I pulled this out of CVS on my windows desktop.) HTH. David
Re: [OT-ish] Session refresh philosophy
On Tuesday 19 February 2002 02:55 pm, Perrin Harkins wrote: > Incidentally, this is mostly the same thing as what Jeffrey Baker mentioned > a few days ago about storing state entirely inside a cookie with a message > digest. The only difference is that by sticking it in a form element > you're attaching it to a specific page. That's not a bad idea. I guess if you're paranoid about snooping you could always encrypt the cookie. -- Milo Hyson CyberLife Labs, LLC
Re: [OT-ish] Session refresh philosophy
At 05:55 PM 2/19/2002 -0500, Perrin Harkins wrote: >Incidentally, this is mostly the same thing as what Jeffrey Baker mentioned >a few days ago about storing state entirely inside a cookie with a message >digest. The only difference is that by sticking it in a form element you're >attaching it to a specific page. True. I was very intrigued by his approach, and might use something like that to increase the security of my app by verifying the hidden form field contents. I suppose I could follow his approach, but the amount of data I need to store could possibly overwhelm the 4KB cookie limit. In this case, simple was better - simple application, simple session. And I know I can count on every browser implementing forms. :-) Drew Drew Taylor JA[P|m_p|SQL]H http://www.drewtaylor.com/ Just Another Perl|mod_perl|SQL Hacker mailto:[EMAIL PROTECTED] *** God bless America! ***
Re: [OT-ish] Session refresh philosophy
> And that is what I am doing for a small project I'm working on now. In my > case, I'm not sure about the capabilities of the remote server, and I know > for sure that I don't have a database available, so session information is > saved via hidden form fields. It's primitive, but was actually a bit of a > challenge to make sure a (unused) hidden field and a visible form element > don't appear in the same . Not my first choice, but it definitely works. Incidentally, this is mostly the same thing as what Jeffrey Baker mentioned a few days ago about storing state entirely inside a cookie with a message digest. The only difference is that by sticking it in a form element you're attaching it to a specific page. - Perrin
Re: [OT-ish] Session refresh philosophy
And that is what I am doing for a small project I'm working on now. In my case, I'm not sure about the capabilities of the remote server, and I know for sure that I don't have a database available, so session information is saved via hidden form fields. It's primitive, but was actually a bit of a challenge to make sure a (unused) hidden field and a visible form element don't appear in the same . Not my first choice, but it definitely works. Drew At 11:42 AM 2/19/2002 +, Ged Haywood wrote: >Hi there, > >On Mon, 18 Feb 2002, Milo Hyson wrote: > > > maybe I'm just approaching the problem incorrectly. If one is doing a > > shopping-cart-style application (whereby someone selects/configures > multiple > > items before they're ultimately committed to a database) how else would > you > > do it? There has to be some semi-persistent (i.e. inter-request) data > where > > selections are stored before they're confirmed. > >You can for example send a hidden object back and forth between >your Client and the app. Drew Taylor JA[P|m_p|SQL]H http://www.drewtaylor.com/ Just Another Perl|mod_perl|SQL Hacker mailto:[EMAIL PROTECTED] *** God bless America! ***
Re: Session refresh philosophy
Perrin Harkins writes: > Actually, even this stuff could be put into a normalized "sessions" table > rather than serialized to a blob with Storable. It just means more work if > you ever change what's stored in the session. This is a tough question. If you store it in a blob, you can't query it with an ad hoc SQL query. If you store it in a table, you have to deal with data evolution. On the whole, I vote for tables over blobs. My reasoning is that you have to deal with data evolution anyway. We have had about 200 schema changes in the last two years, and very few of them have had anything to do with user/visitor state. Rob
Re: Session refresh philosophy
> In that the general idea of expiration is to discard > information that hasn't been accessed in a while, some feel that updating the > timestamp is best done during both loading and storing. If you don't always store the session (Apache::Session doesn't store unless you modify data in the session) then you have to update the timestamp on load to be accurate. If you want to be frugal, you might make the store operation update the timestamp, and then install a cleanup handler that will update the timestamp only if the session was not stored. - Perrin
Re: Session refresh philosophy
> As I understand it, the session data is "state" which is committed to > the database on each request (possibly). It would seem to me that > instead of denormalizing the state into a separate session table, you > should just store it in a normal table. The typical breakdown I use for this is to put simple state information that connects this browser to long-term data in the session, and everything else in normal database tables. So, I put the user's ID (if this session belongs to an identified user), a flag telling whether or not this user has given a secure login so far in this session, and not much else in the session. Actually, even this stuff could be put into a normalized "sessions" table rather than serialized to a blob with Storable. It just means more work if you ever change what's stored in the session. - Perrin
Re: Session refresh philosophy
Milo Hyson writes: > shopping-cart-style application (whereby someone selects/configures multiple > items before they're ultimately committed to a database) how else would you > do it? There has to be some semi-persistent (i.e. inter-request) data where > selections are stored before they're confirmed. As I understand it, the session data is "state" which is committed to the database on each request (possibly). It would seem to me that instead of denomalizing the state into a separate session table, you should just store it in a normal table. If the data needs to be expired, then it can be time stamped when it is written. The point is that it's always simpler to use the existing tables directly rather than making a copy and storing it in the database somewhere else. This usually reduces the code by half or more, because you don't have to worry about making the copy in the first place. Simpler code is more reliable and usually runs faster. To me, sessions are negativist. My expectation is that users will end up clicking OK (making the purchase). If that is the case, you are much better off putting the data were belongs right from start. You may bind it to an ephemeral entity, such as a shopping cart, but when the order is complete the only thing you have to do is free the cart and replace it with an order. The items, amounts, and special considerations have already been stored. If most of your users are filling shopping baskets and walking away from them, it may be a problem with the software. Checkout http://www.useit.com for some ideas on how to improve the ratio. Often you can avoid any server side persistence by using hidden fields in the forms. We use this technique extensively, and we have encapsulated it so that it is easy to use. For example, you might have a sub form which asks the user to fill in an address. When the user clicks on the "fill in address" button, the server squirrels away the context of the current form in the hidden fields of the address form. When the user clicks OK on the address form, the fields are stuffed back into the original form including the new address. If you have a performance problem, solve it when you can measure it. Sessions can mitigate performance problems, but so can intelligent caching, which avoids statefulness in the client-server protocol. Rob P.S. For sample sessionless sites, visit http://www.bivio.com and http://petshop.bivio.biz (which runs on a 3 year old 300mhz box running Apache and Postgres).
Re: [OT-ish] Session refresh philosophy
Hi there, On Mon, 18 Feb 2002, Milo Hyson wrote: > maybe I'm just approaching the problem incorrectly. If one is doing a > shopping-cart-style application (whereby someone selects/configures multiple > items before they're ultimately committed to a database) how else would you > do it? There has to be some semi-persistent (i.e. inter-request) data where > selections are stored before they're confirmed. You can for example send a hidden object back and forth between your Client and the app. 73, Ged.
Re: Session refresh philosophy
On Monday 18 February 2002 07:29 pm, Rob Nagler wrote: > I may be asking the wrong question: is there a need for sessions? > This seems like a lot of work when, for most applications, sessions > are unnecessary. I don't see how they could be unnecessary for what we're doing. Then again, maybe I'm just approaching the problem incorrectly. If one is doing a shopping-cart-style application (whereby someone selects/configures multiple items before they're ultimately committed to a database) how else would you do it? There has to be some semi-persistent (i.e. inter-request) data where selections are stored before they're confirmed. -- Milo Hyson CyberLife Labs, LLC
Re: Session refresh philosophy
Milo Hyson writes: > 1) A fix-up handler is called to extract the session ID from a cookie. [snip] > 1a) If for some reason no session was found (e.g. no cookie) a new one is [snip] > 2) During content-generation, the application obtains the session reference [snip] > 3) A clean-up handler is called to re-serialize the session and stick it back I may be asking the wrong question: is there a need for sessions? This seems like a lot of work when, for most applications, sessions are unnecessary. Rob
Session refresh philosophy
Like my previous question on object caching, this one is potentially a matter of style as well. When it comes to implementing expirations on session data, I've encountered two schools of thought on when is best to refresh the timestamp/expiration. In that the general idea of expiration is to discard information that hasn't been accessed in a while, some feel that updating the timestamp is best done during both loading and storing. After all, both are considered accessing the data. However, taking into account the general pattern of HTTP request processing, I feel that updating only during storage is best, especially when using a database for persistence. Suppose one has a SQL table for saving session data. When a request comes in, the session is loaded and its expiration is examined. Assuming the session is still valid, one could issue another statement to the database to refresh the session's expiration time. That's two database ops before the session is even used. If you count the one at the end for storing the session back in the database it's a total of three per request. My feeling is that if you're going to be writing the session back within (hopefully) a fraction of a second anyway, you might as well wait until then to refresh the time-out. The project I'm working on requires that I design a custom application platform for current and future projects. My proposed solution to the session management problem is as follows: 1) A fix-up handler is called to extract the session ID from a cookie. Assuming a valid ID was found, the session is loaded, de-serialized and checked for expiration. If all is well, the a reference to the session is stored in pnotes for use by the application. 1a) If for some reason no session was found (e.g. no cookie) a new one is created and a new cookie is stuffed in the outgoing headers. 2) During content-generation, the application obtains the session reference from pnotes and uses it as necessary. 3) A clean-up handler is called to re-serialize the session and stick it back in persistent storage (updating the expiration in the process). The handler of course does nothing if the application destroyed the session in step 2. I'm still fairly new to mod_perl and haven't fully taken apart all of the various application servers out there to see how they do it. I would still appreciate any feedback anyone may have on the above. Thanks in advance. -- Milo Hyson CyberLife Labs, LLC