Discussions

News: Storing Session State on the Client

  1. Storing Session State on the Client (42 messages)

    Greg Murray has posted an example of storing servlet session state solely in the browser, eliminating the shared session scope entirely, and details its use in Sun's BluePrints Solutions Catalog.

    It works by creating a tag that, on page rendering, dumps a serialized version of the request scope's attributes into an HTML form. When that form is submitted back to the server, a utility class deserializes the attributes back into the request scope.

    This can help avoid some issues relating to reposting a form. For example, if we imagine an object that counts a number of hits, reposting the browser page (e.g., through the back button) would deserialize the counter object from the client each time, retaining the number of hits until the sequence was changed, rather than continually updating an object in the servlet session.

    However, this obviously applies only to objects that are in the session and have no side effects such as updates in a database.

    It also implies that the client is trusted, since it's conceivable that anyone could look at the serialized content and remotely deserialize it.

    What do you think of this idea? The benefits at first glance seem pretty useful, but do the drawbacks outweigh the ability to ignore the session feature that servlets offer?

    Threaded Messages (42)

  2. This is also a feature built into Tapestry 4.0 (currently in alpha). To make a page or component property persist on the client, you add

    <property name="myProperty" persist="client"/>

    to the page or component specification. Tapestry takes it from there ... serializing all client-persistent data into query parameters, added to URLs or encoded as hidden form fields.

    A longer discussion of this: http://howardlewisship.com/blog/2005/04/property-persistence-on-client.html

    There are some questions; security is one (could a clever hacker affect your application). Another is the size of the generated URLs (not a problem for form submissions).
  3. Encryption?[ Go to top ]

    security is one (could a clever hacker affect your application).

    It seems like both the blueprint mentioned and Tapestry 4 could use a bit of encryption to address this -- obviously, this could significantly increase the data size, so you'd want to be able to tune appropriately.

    -Patrick
  4. Encryption?[ Go to top ]

    I doubt that encryption would be an easy solution to security issues. Firstly, if there is no state on the server, the same encryption algorithm would realistically have to be used to for every request from every user (otherwise you'd need some sort of state stored in a session on the server). This does not compare to SSL, where essentially a new algorithm is created for every secure session (with new keys). So once the serialized data encryption algorithm was cracked, as far as a hacker would be concerned, any serialized data passed to any client would be as good as unencrypted.

    Even so, SSL could help to prevent interception of the serialized data by a third party, but that doesn't protect against the hacker and the user being the same person. In this instance there'd be the same issues as inappropriately using hidden fields instead of storing secure state in HttpSession. For example:

    - The user (hacker) can modify primary keys stored in the client-side session state, resulting in updates to other people's data rather their own.
    - A shopping bill total serialized to the client could be modified (reduced to $1).

    I find it hard to think of many applications requiring sessions of some sort that don't have security issues that would make such an approach problematic.
  5. Encryption?[ Go to top ]

    For example:- The user (hacker) can modify primary keys stored in the client-side session state, resulting in updates to other people's data rather their own.- A shopping bill total serialized to the client could be modified (reduced to $1).I find it hard to think of many applications requiring sessions of some sort that don't have security issues that would make such an approach problematic.

    Really, you have to draw the line between application state and view state. JSF handles view state. While I completely agree with your concerns, the blame would need to be put back on the developer failing to know the bounds of the technology.

    -- Jacob
  6. In this tag, we already implement a secure solution. The Tag encrypts the state that is stored on the client. The key for encryption is NEVER stored on the client or sent on the wire. The encryption is done with strong cryto (3DES) and a Message authentication code (SHA1 MAC) with a secure-random initialization vector for additional security. The encryption keys are created secure-randomly for each client, and stored in the HttpSession (the strategy to create and store encryption keys is pluggable). I believe it is very hard to break the security of this solution.

    Read the security strategy as illustrated in the main document as well as in the section on design details at the Solutions Catalog website. The utility class that does encryption is available in the references section of the document on design details.
  7. In this tag, we already implement a secure solution. The Tag encrypts the state that is stored on the client. The key for encryption is NEVER stored on the client or sent on the wire. The encryption is done with strong cryto (3DES) and a Message authentication code (SHA1 MAC) with a secure-random initialization vector for additional security. The encryption keys are created secure-randomly for each client, and stored in the HttpSession (the strategy to create and store encryption keys is pluggable).

    That sounds a lot more reasonable, but of course it's no longer a stateless solution. There'd be plenty of potential to considerably reduce the memory required by HttpSession, however :)

    To be fair, it does seem to have been the serverside post rather than the original blog that used the phrase "storing servlet session state solely in the browser, eliminating the shared session scope entirely".
  8. Security analysis[ Go to top ]

    In this tag, we already implement a secure solution. The Tag encrypts the state that is stored on the client. The key for encryption is NEVER stored on the client or sent on the wire. The encryption is done with strong cryto (3DES) and a Message authentication code (SHA1 MAC) with a secure-random initialization vector for additional security. The encryption keys are created secure-randomly for each client, and stored in the HttpSession (the strategy to create and store encryption keys is pluggable). I believe it is very hard to break the security of this solution. Read the security strategy as illustrated in the main document as well as in the section on design details at the Solutions Catalog website. The utility class that does encryption is available in the references section of the document on design details.

    It seems that there some secutity gaps in this BluePrint. I've posted some details and possible improvements in my blog. However those improvements most probably decrease usefullnes of such solution.
  9. Eugene,

    Thanks for the detailed comments in your blog. I would like to clarify a few things since I dont think the security issues that you raise are valid:

    It is incorrect to say that knowing MAC and IVs compromises the security. In any encryption, MAC and IVs are always publicly known. MAC is run on IV + ENCDATA, so ENCDATA can not be changed without changing the MAC, and any changes can easily be detected at the server-side when the client submits a maliciously-crafted request. The purpose of IV (which is chosen randomly everytime) is to avoid the replay attacks by ensuring that the output of the encryption is different everytime the same content is encrypted. Also, the client CAN NOT generate a new MAC, since to generate the MAC, you need to know the password/keys which the client does not have.

    Inderjeet Singh
  10. Eugene, Thanks for the detailed comments in your blog. I would like to clarify a few things since I dont think the security issues that you raise are valid: It is incorrect to say that knowing MAC and IVs compromises the security. In any encryption, MAC and IVs are always publicly known. MAC is run on IV + ENCDATA, so ENCDATA can not be changed without changing the MAC, and any changes can easily be detected at the server-side when the client submits a maliciously-crafted request. The purpose of IV (which is chosen randomly everytime) is to avoid the replay attacks by ensuring that the output of the encryption is different everytime the same content is encrypted. Also, the client CAN NOT generate a new MAC, since to generate the MAC, you need to know the password/keys which the client does not have.

    The BluePrint document is suggesting to use SHA1 for the MAC and there is no password for SHA1 algorithm, so it has no secret and can be recreated for tampered data.

    As I said in my blog, there is a potential issue. I'm not aware of practical attacks to DES3/CBC, but I'd really like to hear a competent opinion, because in this situation, attacker may have quite enough control on the plain text.

    Why don't you ask Dr. Whitfield Diffie, Chief Security Officer at Sun to take a look at this and then share his opinion to the community.
  11. MAC does use a Key[ Go to top ]

    Hi Eugene,

    Your assertion is NOT correct. MAC algorithm does use a key for initialization. Here is a code sample from ByteArrayGuard class about how this is done:

    byte[] rawKey = convertPasswordToKey(getPasswordToSecureState());
    ----
    Mac mac = Mac.getInstance("HmacSHA1");
    SecretKeySpec key = new SecretKeySpec(rawKey, 0, macLength, "HmacSHA1");
    mac.init(key);

    Also notice that Mac is run on the IV as well as ENCDATA while encrypting:
    mac.update(iv);
    mac.update(encdata);

    As I said in my blog, the solution applies principles from CS255 taught by Dan Boneh who is a well-known expert in the field of cryptography. Feel free to ask Whitfield Diffie if you would like.
  12. SHA1 is mot MAC[ Go to top ]

    Hi Eugene, Your assertion is NOT correct. MAC algorithm does use a key for initialization. Here is a code sample from ByteArrayGuard class about how this is done: byte[] rawKey = convertPasswordToKey(getPasswordToSecureState());----Mac mac = Mac.getInstance("HmacSHA1");SecretKeySpec key = new SecretKeySpec(rawKey, 0, macLength, "HmacSHA1");mac.init(key);Also notice that Mac is run on the IV as well as ENCDATA while encrypting: mac.update(iv);mac.update(encdata);As I said in my blog, the solution applies principles from CS255 taught by Dan Boneh who is a well-known expert in the field of cryptography. Feel free to ask Whitfield Diffie if you would like.

    My confusion came from your blog where referring to SHA1 algorithm. HmacSHA1 obviously makes more sense. However it will be a good idea to get some comments from credible cryptographers about whole scenario and I thought it should be easy to you to talk to your Sun Fellow colleague at Sun. I gues it is part of his work to keep an eye on all security aspects of Sun technologies.
  13. Why do you claim that the encryption will result in increased size? As long as the compression is done BEFORE the encryption, the data size will not be significantly affected by encryption. The encryption just adds a couple of bytes for initialization vector and the MAC.

    Inderjeet Singh
  14. From TFA:
    Navigation must be from a form - The state is kept as HTML form hidden variables requiring page to page navigation to be from a form though links could use JavaScript to perform a form submit.

    Seems like that bit of JavaScript -- plus something on the server tier to convert all anchors appropriately -- would be a pretty important piece of this blueprint.

    -Patrick

    --
    Patrick Linskey
    http://solarmetric.com
  15. Javascript links?[ Go to top ]

    From TFA:
    Navigation must be from a form - The state is kept as HTML form hidden variables requiring page to page navigation to be from a form though links could use JavaScript to perform a form submit.
    Seems like that bit of JavaScript -- plus something on the server tier to convert all anchors appropriately -- would be a pretty important piece of this blueprint.-Patrick--

    Not to mention crawlers would have a nightmare crawling through your site. The idea of form submissions for all requests is, IMO, going to keep this from going past an intranet site. Plus, how would you handle dynamic content that is stored outside of your code base? Would you have to parse it, converting links into form submissions? Uck.

    This technique has its place and I'm sure it will be used. But I doubt it would become mainstream, especially considering all the technologies available for session failover. Sites with large sessions would definitely not use this. And on the flip side, sites with small sessions could probably get away with storing state in cookies. A lot simpler than modifying all links.

    Mike Schanberger
  16. It is also possible to store small session state in a cookie ;-)

    These types of patterns can be very good if (and only if) the application developers are very deliberate and precise about what they store in their sessions. Quite often it involves a lot of custom work. The benefits can be worth it, particularly if the session data is only (total) a few hundred bytes.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Cluster your POJOs!
  17. Storing Session State on the Client[ Go to top ]

    It is also possible to store small session state in a cookie ;-)
    And now that the Cookie Monster has sworn off cookies, no fear of them being gobbled up.
  18. So a few hundred bytes in the cookie can become 20 KB. I take it that you give up your resistance against stateless servers then? That was the last topic where we disagreed. How sad!

    I can not find a single topic to discuss anymore. You have given up all your earlier vehemently maintained points and views and now we have run out of topics. "What shall we talk about"?* "Where shall I find a new adversary so close to my on level"*
    Rolf: "If you know from the beginning that your application is going to be clustered you should make it 100% stateless, which means that you must handle your sessions yourself, not use any container dependent sessions, no container variables at all, and of course only relative paths. If you keep to these simple rules clustering is a piece of cake."

    Cameron: If you stick to those rules, it's probably not clustering ;-)
    Don't get fluster clucked


    Regards
    Rolf Tollerud
    (* from "Raiders of the Lost Ark" 1981)
  19. compression[ Go to top ]

    Would there be any value in compressing it or would that add too much overhead?
  20. compression[ Go to top ]

    Would there be any value in compressing it or would that add too much overhead?

    That depends -- one of the benefits of reducing / eliminating server-side state is that you can more easily build a cluster for handling requests, so you can scale more easily. If improved scalability is the reason to go this route, then any server-side performance degradation is often dwarfed by the increased scalability of the system.

    -Patrick

    --
    Patrick Linskey
    http://solarmetric.com
  21. compression[ Go to top ]

    Would there be any value in compressing it or would that add too much overhead?

    Tapestry compresses the ObjectOutputStream and uses that, unless the uncompressed bytestream is smaller (which is often is).
  22. Side effects[ Go to top ]

    I first used a similar approach on a project back in 2000. It works well for certain purposes but there are definite side effects, some less obvious than others.

    - Page sizes - BASE64 encoding serialized java objects can produce rather large globs of data is one is not careful.
    - Page caching on the browser becomes an issue for a couple of reasons
    1. If you send back state which is used for any kind of transactional purposes (either directly or indirectly) when the form is submitted, you can easily get into data integrity issues. If a page containing state is cached on the client, and the user later goes back to it (using the back button) and submits the form again, the action will be performed using the state which was valid when that form was rendered but that state might very well be 'stale' or invalid at the point the user submits it again (due to the user having taken other actions in the application).
    2. A more subtle side effect (and less severe since chances of encountering it is less) has to do with java class versioning. It is possible that a page cached on the client would be submitted and the de-serialization of the state would fail if changes has been made to the class being serialized.


    Micsrosoft actually has this kind of page level state as a built-in feature in ASP.NET. It is called the 'Viewstate' and is used primarily for keeping track of the state of the UI components on the page (e.g. contents of drop-downs etc.).
    This is actually a good indication of what type of state this type of pattern is best suited for, i.e. non-transactional related state.
  23. Externalizing component state is also on the TODO list for Wicket 1.1 (we'll be working on that this summer).

    I think it is a disadvantage of JSF and .NET that the requests have to be submits. Wicket doesn't want to impose that on its users (like Tapestry doesn't), though get GET request string length is obviously pretty limited.

    Anyway, besides supporting serialization as a default way of externalizing, we also want users to be able to use their own, more efficient, methods.
  24. JSF Already Does This[ Go to top ]

    JSF already can flip between storing state on the server/client with one init-param in your web.xml. For saving state in the client, state is serialized in a zip stream and output in Base64.

    Security wise, this is more than doable. It's already been brought up in the EG and not hard to implement with JSF.

    Jacob Hookom (JSR 252 EG)
    JSF Facelets
  25. JSF Already Does This[ Go to top ]

    Yes, but for client saving, all requests have to be POST requests. Furthermore, do you as a user have full control of how the translation of state to a string happens?

    Eelco
  26. JSF Already Does This[ Go to top ]

    Yes, but for client saving, all requests have to be POST requests. Furthermore, do you as a user have full control of how the translation of state to a string happens?

    Eelco

    StateSaving is delegated to a StateManager, as part of the application. This can be swapper/wrapped/extended however you want to provide alternate behavior.

    In relation to the new JSF 1.2 spec, there's no longer, nor really was a requirement for the request to be a POST. The underlying issue is that with the VIEW_STATE being serialized into the page, that you can reach the max length for a URL with a GET.

    Jacob Hookom (JSR 252 & EL)
    JSF Facelets
  27. JSF Already Does This[ Go to top ]

    StateSaving is delegated to a StateManager, as part of the application. This can be swapper/wrapped/extended however you want to provide alternate behavior.In relation to the new JSF 1.2 spec, there's no longer, nor really was a requirement for the request to be a POST.

    If it never was a requirement to use POSTS, it is probably a misconception that many people have about JSF. Anyway, sounds really good, thanks for informing!

    Eelco
  28. JSF Already Does This[ Go to top ]

    If it never was a requirement to use POSTS, it is probably a misconception that many people have about JSF. Anyway, sounds really good, thanks for informing!

    Eelco

    To get a little more 'techie', JSF's RenderKits (such as XHTML) can now interpret where/how the VIEW_STATE is retrieved, if at all, by the StateManager you provide.

    I believe a lot of the other comments in this thread are quite valid with managing session state, but to clarify this a bit, JSF's StateManager is meant to retain view state, not the transaction state of a business process. This feature does correct issues with back/forward buttons, but doesn't replace the need for transaction management as another person pointed out.

    I actually attended a talk from Gavin King (Hibernate/EJB3) last night (Minneapolis OTUG). He spent some time describing JSF and EJB3 integration in order to manage conversation or transaction state across multiple calls. For anyone that's used Hibernate or JSF, linking the two into a View/Controller/Persistence add-on would be a beautiful thing.

    --Jacob Hookom (JSR 252 EG)
  29. JSF Already Does This[ Go to top ]

    JSF's StateManager is meant to retain view state, not the transaction state of a business process. This feature does correct issues with back/forward buttons, but doesn't replace the need for transaction management as another person pointed out.

    True, surely most developers are familiar with layered application concepts. Btw, with Wicket we have the concept of 'detachable models' to help people do handle any transaction management they want themselves, as 'Wicket is a web UI framework that delegates as many areas of responsibility as possible to other, more focused tools and techniques' (that's from Jonathan's vision document)

    But enough plugging now ;) I think client state is a good addition to a webapp toolbox - as long as you have the choice whether and how you want it for a specific situation.
  30. JSF Already Does This[ Go to top ]

    JSF's StateManager is meant to retain view state, not the transaction state of a business process. This feature does correct issues with back/forward buttons, but doesn't replace the need for transaction management as another person pointed out.
    In other words: instead of synchronizing view state with stale fields of HTTP form, it is suggested to synchronize model state with stale view state. How is this better?
  31. JSF Already Does This[ Go to top ]

    JSF's StateManager is meant to retain view state, not the transaction state of a business process. This feature does correct issues with back/forward buttons, but doesn't replace the need for transaction management as another person pointed out.
    In other words: instead of synchronizing view state with stale fields of HTTP form, it is suggested to synchronize model state with stale view state. How is this better?

    Again, I think you are confusing view or page state with application state. JSF provides a clean separation between the two where the issues you are describing are not relevant.

    So when I say that an inputText component is updating #{loginForm.name}, the value isn't serialized in the view state, only the expression you wish to evaluate. This means that application state is managed at the controller/object level within (loginForm). The fact that inputText points to #{loginForm.name} is a concern of view state-- that's it.

    When I say that a dataTable is populated with #{accounts}, the account List isn't serialized, just the fact that the dataTable is supposed to use whatever's located at #{accounts}.
  32. JSF Already Does This[ Go to top ]

    I think you are confusing view or page state with application state. JSF provides a clean separation between the two where the issues you are describing are not relevant.So when I say that an inputText component is updating #{loginForm.name}, the value isn't serialized in the view state, only the expression you wish to evaluate. This means that application state is managed at the controller/object level within (loginForm).

    The fact that inputText points to #{loginForm.name} is a concern of view state-- that's it.When I say that a dataTable is populated with #{accounts}, the account List isn't serialized, just the fact that the dataTable is supposed to use whatever's located at #{accounts}.
    I guess my English is too bad to understand what you just said. This is how I see it, please correct me where I am wrong:
    * there is the loginForm bean, which is a part of the model/appstate
    * loginForm bean is either stored in the session or loaded/created each time data is submitted or page is rendered by server
    * there is a viewstate, which is generated on server just before the page is sent to the client. It is stored in request object, and then sent to client as hidden field.
    * viewstate hidden field does not contain data from visible HTML form fields. Or does it? The java.net blog says different: "The data you manipulate is what was on the page that was posted from".
    * on the other hand, viewstate hidden field does not contain other viewstate values either, only references to the model/appstate, because you said that "the value isn't serialized in the view state, only the expression you wish to evaluate" (?) Translate, please ;) How can you talk about state without actual values?
    * The page is submitted, values go to... to the viewstate? When they are stored in the model?
    * When Back is clicked, stale page is shown. It contains stale viewstate, but the loginForm was already updated. Or was not it?
    * A user changes value or submits the same values, they go to the server, and are applied to decrypted viewstate first. They the viewstate is applied to the model? If yes, we need to sync viewstate and appstate, if no, then I don't get when the loginForm is actually updated. I would appreciate if you explained that.
  33. JSF Already Does This[ Go to top ]

    I realize this is a little OT to the topic, but worthwhile in drawing boundaries in client state management:
    there is the loginForm bean, which is a part of the model/appstate, loginForm bean is either stored in the session or loaded/created each time data is submitted or page is rendered by server

    This is true, the loginForm is provided by some other manager, seperate from the view management.
    there is a viewstate, which is generated on server just before the page is sent to the client. It is stored in request object, and then sent to client as hidden field.

    Yep!
    viewstate hidden field does not contain data from visible HTML form fields. Or does it? The java.net blog says different: "The data you manipulate is what was on the page that was posted from".

    That should be corrected to say "The components you had on the page are what's posted in the view state". That may sound 'moot', but the goal of the JSF framework is to consolidate controller/view behavior into pages. If you place an h:inputText value="#{login.name}" on 3 different pages, none of them are going to affect each other.
    on the other hand, viewstate hidden field does not contain other viewstate values either, only references to the model/appstate, because you said that "the value isn't serialized in the view state, only the expression you wish to evaluate" (?) Translate, please ;) How can you talk about state without actual values?

    What you are serializing is not your application/form state, just the instructions/makeup of the page. See my last comment. This has lots of benefits with developing in a modular/reusable manner since you can drop a component in a page whose job it is to validate the user input. Note, that user input *value* isn't part of view state-- only your instructions on how to validate the data.
    The page is submitted, values go to... to the viewstate? When they are stored in the model?

    When a request is made back to JSF, JSF grabs the view state from wherever and deserializes it. This now becomes your 'controller', Struts Action, or set of behavior for processing the values you are submitting. The request coming in is processed and new values are applied (such as the login name) and validated according to whatever other components you made part of the page-- and resultingly, the view state.
    When Back is clicked, stale page is shown...

    Of course, but this happens in every framework unless the previous request was a POST or no-cache headers were written.
    ....It contains stale viewstate, but the loginForm was already updated. Or was not it?

    Yes, it was already updated, no different than re-submitting a Struts ActionForm to an Action, then hitting the back button.
    A user changes value or submits the same values, they go to the server, and are applied to decrypted viewstate first. They the viewstate is applied to the model? If yes, we need to sync viewstate and appstate, if no, then I don't get when the loginForm is actually updated. I would appreciate if you explained that.

    Yes, this is true. This is why I'm saying that JSF takes care of managing the view, but not application state or the model.

    I would recommend looking at the 5 step process used in JSF:
    Restore The View, Apply Request To the View, Validate, then Update Model/Application, finally Render Response.

    I realize this method of development is different that our usual MVC2, but think of view state as packaging the view and the controller in the same document. Same thing as struts, just a different way of updating your model.

    -- Jacob
  34. JSF Already Does This[ Go to top ]

    That may sound 'moot', but the goal of the JSF framework is to consolidate controller/view behavior into pages. If you place an h:inputText value="#{login.name}" on 3 different pages, none of them are going to affect each other.

    That depends. If the 'login' bean has request scope this is probably true. If it has session or application scope then those 3 different pages will all be referring to the 'name' property of the same object, so they will affect each other.
  35. JSF Already Does This[ Go to top ]

    That may sound 'moot', but the goal of the JSF framework is to consolidate controller/view behavior into pages. If you place an h:inputText value="#{login.name}" on 3 different pages, none of them are going to affect each other.
    That depends. If the 'login' bean has request scope this is probably true. If it has session or application scope then those 3 different pages will all be referring to the 'name' property of the same object, so they will affect each other.

    I was referring to the component itself (h:inputText)-- unless of course if they use "binding" where they would want to mark the component as transient.
  36. JSF Already Does This[ Go to top ]

    What you are serializing is not your application/form state, just the instructions/makeup of the page. See my last comment. This has lots of benefits with developing in a modular/reusable manner since you can drop a component in a page whose job it is to validate the user input. Note, that user input *value* isn't part of view state-- only your instructions on how to validate the data.
    I thought that I got it, but here I got lost again. What is the point of sending code, which is not updated, to the client? It does not save session memory, since code is not stored in session and should not be replicated in the cluster. Also, again about values. You say that values are not serialized. Say, we sumbitted a form, it has errors, and it should be redisplayed. Where do values come from? Or if I store viewstate on the server (like most JSF examples do), and refresh a page. Where do values come from? I guess, from the viewstate. So, viewstate DOES store page values (but not model values, did you mean that)?
    In this tag, we already implement a secure solution. The Tag encrypts the state that is stored on the client. The key for encryption is NEVER stored on the client or sent on the wire. The encryption is done with strong cryto (3DES) and a Message authentication code (SHA1 MAC) with a secure-random initialization vector for additional security. The encryption keys are created secure-randomly for each client, and stored in the HttpSession (the strategy to create and store encryption keys is pluggable).
    That sounds a lot more reasonable, but of course it's no longer a stateless solution.
    Right, which eliminates the only possible reason for this pattern. There are no other benefits of it except for reducing session size, which I do not consider important enough to eclipse its deficiencies.

    Having request-scope viewstate works only in one situation: if an error was made after postback, and page should be shown again. In this case viewstate is in sync with model. But even in this case I cannot safely reload a page. If I click Back and resubmit, server will restore stale viewstate and update it with stale resubitted data. Thus, I would need to synchronize model state with stale view state.

    I think that server-side viewstate object is tremendously convenient if I do a redirect, or if I leave a page and then come back again, it keeps my values. JSF already implements server-side viewstate which works very well, why bother copying obsolete patterns from ASP.NET?
  37. JSF Already Does This[ Go to top ]

    What you are serializing is not your application/form state, just the instructions/makeup of the page. See my last comment. This has lots of benefits with developing in a modular/reusable manner since you can drop a component in a page whose job it is to validate the user input. Note, that user input *value* isn't part of view state-- only your instructions on how to validate the data.
    I thought that I got it, but here I got lost again. What is the point of sending code, which is not updated, to the client? It does not save session memory, since code is not stored in session and should not be replicated in the cluster.

    The viewstate is unique on a per user basis. Using h:inputText isn't probably the best example for the potential JSF component, but think of viewstate as the Action and ActionForm combined into one, and sent with the page or saved in the session for validating the request.
    Also, again about values. You say that values are not serialized. Say, we sumbitted a form, it has errors, and it should be redisplayed. Where do values come from?

    You get the values from #{loginForm.name}, same as Struts input tags basically.
    Or if I store viewstate on the server (like most JSF examples do), and refresh a page. Where do values come from? I guess, from the viewstate. So, viewstate DOES store page values (but not model values, did you mean that)?

    Yeah, that's what I should have said.
  38. Stale wine .....[ Go to top ]

    For those who remember: The car hire company SIXT (then I believe still called Sixt Budget) did this ca. 1999. So much for novelty. From a security point of view it is a nightmare, as "totally eliminating" server state does not work and is not desirable. As an example think about the process for ordering shares. Clicking back and forth will allow you to reorder multiple times. Hell, it'll allow anyone to strip your account just by repeating your requests. Bizarre thought, but altogether possible. That is for intentional misuse. And of course you would need to prevent accidental misuse as well, which essentially amounts to making each and every request a post request, because you need to prevent yourself against the back button.

    Where it might be usable is if navigating (unsecured) decision trees or content collections, where "application state" actually means "page context". Somehow, I would think that the idea that these are different things should by now be understood.....
  39. Pre-cookie era[ Go to top ]

    Even before 1999. Before cookies were introduced this was a standard method. The perl CGI.pm module had features to enable this in forms.
  40. Greg Murray has posted an example of storing servlet session state solely in the browser, eliminating the shared session scope entirely, and details its use in Sun's BluePrints Solutions Catalog.It works by creating a tag that, on page rendering, dumps a serialized version of the request scope's attributes into an HTML form. When that form is submitted back to the server, a utility class deserializes the attributes back into the request scope.

    This is not storing session state in the browser, this is storing state in between browser and server in HTTP request/response objects, and passing it back and forth bogging the network. In Microsoft parlance this is called _viewstate. This is the part of ASP.NET I dislike most. Raymond Chen noticed in his blog that network in Microsoft headquarters is overloaded almost twice comparing to network load test. With these technologies we can see the reason.

    _viewstate is user-unfriendly: when a user navigate to a different site, and then navigates to the previous site, the state is gone. It is developer-unfriendly: _viewstate does not support redirection, unless you stick this field in the redirect response/request manually as query parameter. _viewstate encourages responding with result page directly on POST request and requires all pages to be HTML forms. It is application-unfriendly: going back and submitting the page sends state information which may not be relevant anymore. It is network-unfriendly: passing tens of kilobytes only to keep the state of your list or table, and you may even not use it during the course of application! It is server-unfriendly: synchronizing _viewstate with client and ensuring that it is intact requires versioning and encryption. All that for keeping session a little smaller? Yuck.
    This can help avoid some issues relating to reposting a form. For example, if we imagine an object that counts a number of hits, reposting the browser page (e.g., through the back button) would deserialize the counter object from the client each time, retaining the number of hits until the sequence was changed, rather than continually updating an object in the servlet session.

    It is easier to use tokens for hit counting. And for everything else using real objects seems more logical. Object is displayed on a page with timestamp hidden field and/or state hidden field. Object is updated, submitted, persisted. Now click back and sumbit the same changes, this would fail because either the object state was changed, or the timestamp is older that current object timestamp on the server, or the object was removed from server altogether like a shopping cart. _viewstate? What _viewstate?
  41. Javaworld Cookie Article[ Go to top ]

    Also on this topic is a Java object serialized in Cookies:

    http://www.javaworld.com/javaworld/jw-01-2001/jw-0126-servlets-p3.html
  42. Days of perl[ Go to top ]

    Yeah .... people were doing that back in the perl CGI days ...
    and it sucked. I bet sun have probably patented this ...

    -b

    ( although we didn't have these "taglib" whatdeycallitthingimejigs then )
  43. See some critique of this pattern in my blog