I want to use a cookie based HttpSession in a serlvet container. All session data should be stored inside the cookie. It seems to be uncommon within servlet applications. In Rails (Session) and Playframework (Session), this kind of session handling is the default. Why is this so uncommon?
In concrete I need a solution for JBoss EAP6 (without session scoped beans). I found two implementations based on serlvet filters:
Stateless Servlet Filter "This filter is still in a beta status." 2013
java-stateless-http-session No references for usage and no commit for more than a year. No tests.
Do you know any alternatives?
(If possible I don't want want to discuss pros and cons in general)
It is uncommon in Java EE to have session data persisted in cookie ... because HttpSession is implemented in all servlet containers.
In cookie persistent sessions, you have a limit in size, and you must use signed data to avoid manipulation of session client side. You must crypt data if you want to keep sensitive informations in session. And all session data is exchanged with every request and response. Those limits go away with HttpSession.
The highest interest of cookie persistent sessions is that you can have a farm of multiple servers that can respond to any request, because the session is contained in the request. But this can be done in Java EE by using sticky sessions at a reverse proxy level (because you have reverse proxies in almost every serious data center) : the reverse proxies know about the session and pass a request to the server that holds it.
Some Java EE servers have even a notion of shared sessions.
IMHO it is not that is would be very hard to implement a cookie persistent session in Java, it is simply that for professional usages, it has not been found as important enough.
Related
What's the scenario of share session on server side? And is there some approach to share the session on server side in JAVA EE platform?
As the problem does not explicitly say the objects between which session needs to be shared, I can suggest following options:
1) If you need to share session between different web apps on the same server (tomcat) , you can use:
<Host name="localhost" ...>
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
</Host>
2) If the server is not tomcat, please refer to SSO option for the respective server.
3) You can as well use a full fledged SSO product like CAS (http://www.jasig.org/cas) which will allow you to share sessions across apps across different servers but not between users.
4) If you need to share session between different users, all you need to do is pass on the session ids between different clients (typically browsers) based upon your share criteria like, people playing same game, accessing same bulletin board and can collaboratively changing the data. However, please understand most of the security infrastructure is built around mapping of session ids. If you choose to make the session ids explicitly accessible between multiple users, you would have to re-create lots of security filters yourself.
5) Alternatively, best approach will be to manage the state of the object differently from session. The state of the shared object can be shared across multiple sessions in much more standards compliant secure and auditable way.
On Java EE you must review the Servlet Specification, the object HttpSession provides the behavior for manage the session on the server side.
http://docs.oracle.com/javaee/5/tutorial/doc/bnagm.html
Although you can store any object in the session, this practice can be dangerous because the objects remain on session until it expires or the object is removed, so if your program doesn't manage well the objects that are stored in the session you can consume to many heap memory.
The objects of session are deleted when it expires, the expiration time is configured in the deployment descriptor web.xml or can be set by client. If you don't specify a time for session expiration then the default is 30 minutes, this 30 minutes are counted from the last request made by the user.
My recommendation is that you don't store objects in session, you must use the object HttpServletRequest and the mehtos setAttribute and getAttribute for pass objects between requests. I you need store a value on session you can store the ID of a product instead the whole product. A common use of the session is for store variables that must live for more than a request and you don't want to store it on cockles for security reasons.
We need to enable java servlet sessions support for one Google App Engine project, but session will be used only in one servlet (small isolated part of application).
Would we get some increased latency impact (because of session memcache/datastore object) in other servlets although session object would not be used in any other servlets?
Is there a way to disable sessions support for some servlets ?
There is no way to enable sessions on a per servlet basis.
Also sessions consume a read from memcache and a write to datastore for every request. So this can get costly.
Additionally if your client does not handle cookies (usually devices via REST), then every request will create a new session entity in datastore. And this will grow indefinitely.
The solution is to roll your own sessions - create servlet filter that gets/sets cookies only for certain path/servlet.
thank you you guys for looking at my post.
Due to grey areas in licensing issues, I have two instances of tomcat running. I'm using Apache proxy to seamlessly communicate between the two.
App1 lives in tomcatA.
App2 lives in tomcatB.
Both requires user authentication and uses sessions for storing data. App1 is the only one visible to outside world and all the requests that comes in to App2 are generated by JavaScripts from App1. Unfortunately, App1 has a session and sends that specific JSESSIONID to all the requests from App2. Since there isn't a session with that specific id in App2, it returns with errors.
Is there a way for me to initialize a session with specific id?
Is there a way for me to modify all the requests so that it puts the valid session id into the headers.
Edit: I need App2 to realize that requests coming through, from App1, with a particular session id maps to a session that App2 created.
Even if both application lived in the same Tomcat, sessions would be different as they are issued on a per-app basis. Personally, I am not entirely convinced by this design.
If your question is how to propagate authentication to another app, use a single sign-on application like Josso or a CAS; to share session data, you can use a centralized cache accessible from both applications and accessible through JSON.
And yes, session data is bad.
Update: can't you simply implement a handshake protocol like: app2/register/{app1 session id} - at this point you both hold both session ID's and you can correlate each other. This can be done also with a session listener.
You could just use a different session cookie name (or path, if possible) for your tomcatB. tomcatB would thus consider the JSESSIONID cookie as any other cookie, and not as a session cookie.
See http://tomcat.apache.org/tomcat-7.0-doc/config/context.html.
This is just the continuation of this post.
I'm coming from ASP.NET world. In ASP.NET I had a few options to store the session: "In proc" and "Out Proc" which mean the session will be serialized and stored either in database or in Session management service. This practice is also relevant to load balancing if I don't want to have my session sticky.
what is the Java/tomcat alternate solution for such cases?
How can I store out of proc session?
What is the load balancer solution?
Thank you in advance.
There is no built-in "out proc" session type for J2EE (at least, not one that is known to me). If you need to store "session" type data, but can not use the HttpSession to do so, then you will have to roll your own solution. This is likely to involve the following:
A session identifier that is stored on the client. You will want to use an identifier that is not easily spoofed if your application faces the Internet (versus an internal only app).
An API (maybe just a few classes) on the server side to retreive the session information from somewhere (perhaps a central database).
https://wiki.jasig.org/display/CAS4UM/JPA+Session+Storage
I want the clients of several related web apps to hold their own authentication state. This improves scalability, because no session replication between cluster nodes is needed. And it makes integration of different server technologies like Java Servlets and PHP easier.
My plan is as follows:
Set a signed and encrypted cookie with the user name and session expiration time after client authentication.
When the client sends a request, the server decrypts and validates the cookie and grants or denies access depending on the cookie values.
The session expiration will be updated through resetting the cookie.
All servers that want to use the session have only to know the cookie mechanism and the decryption key. See also: Session state in the client tier
Is this approach ok? Would it be possible to integrate it into a servlet container / application Server so that it is transparent to the applications? A servlet should be able to use HttpServletRequest#getRemoteUser() for example. Is this possible? Or would I need something above the container level like Spring Security? Are there any existing libraries for client side session management?
Not a good idea. Storing vital data like session expiry and user name entirely on client side is too dangerous IMO, encrypted or not. Even if the concept is technically safe in itself (I can't answer that in depth, I'm no encryption expert), a break-in could be facilitated without compromising your server, just by acquiring your encryption key.
Somebody who gets hold of the key could generate session cookies at will, impersonating any user for any length of time, something the classical session concept is designed to prevent.
There are better and scalable solutions for this problem. Why not, for instance, set up a central session verification instance that all associated servers and services can poll? Look around on the web, I am 100% sure there are ready-made solutions addressing your needs.
I disagree with the posters saying this approach is not secure. Variants of it are used in a number of well respected frameworks, such as Rails and Play!, for precisely the reasons you outline, and it's perfectly secure when implemented correctly.
This improves scalability, because no session replication between cluster nodes is needed.
First, using HTTP Session doesn't really prevent you from scaling, even when using HTTP Session State replication (some mechanisms are smarter than others by the way, for example WebLogic's in-memory replication doesn't have a big overhead). Second, do you really need it? Most applications (the majority) don't need Session replication. Third, am I understanding right: do you plan to not use HTTP Session at all?
(...) Set a signed and encrypted cookie with the user name and session expiration time after client authentication.
Don't do this! Don't store a username and other sensible data used by the server in a cookie, this is a very bad idea! You actually need to admit that it's just a matter of time before someone figures out how your system works and breaks it (especially if your cookie is candidate for crib attacks). Sor, really, you should store data in the Session on the server-side and only an ID in the cookie, like things are actually working. This is much more secure.
Is this approach ok?
No. And you don't need this for interoperable single-sign on (if this is what you are trying to build). Just use a centralized authentication solution like CASJasig which has libraries for various technologies.
This is not really how Sessions are implemented. The cookie itself doesn't need to carry any data of the session itself, it's just a reference to it.
What the Cookie holds is usually a Session ID which is then linked to the data on the server.
If you don't have a central data session server for the other servers to access, I suggest to get one :).
You can avoid duplication of data in a clustered environment by using a state server - a server that is well known by all the nodes in the clusters and maintains the session data for all the users. Every time a user performs a request, it send a cookie with session id to the applications server; this one should retrieve the session from the state server. This is possible for asp.net development, but I'm not sure how easy Java supports this approach.
As Pekka said, not a good idea. One can intercept your cookie with sensitive session data. Even with SSL, by using fiddler2 one can decrypt the traffic