Building a JSF application with Spring on Tomcat. The target is a web farm, and the client has requested that we design our application so that it can be load balanced without relying on "sticky sessions" in the LB.
In .NET, you can configure the session store to be SQL Server or the ASP.NET State Service. What alternatives are there in the Java world? Is there a standard way to plug in a different session state store that points to a MySQL database for example? Does Spring provide any hooks?
This is servletcontainer specific which in this case is Tomcat. The servletcontainer is the one which manages and provides the sessions. So JSF and Spring have nothing to do here. They just transparently gets it from the servletcontainer by request.getSession() and so on.
In Tomcat, you can provide a custom session manager implementation in the webapp's Context:
<Context ...>
<Manager className="com.example.SessionManager">
..where com.example.SessionManager implements org.apache.catalina.Manager as per its contract. Therein you can write code to back the sessions by a database.
However, there are alternatives for your particular requirement, you can choose for Tomcat's builtin clustering/session-replication capabilities instead of reinventing it with a custommade manager/database. Read more about it at the Tomcat Clustering/Session Replication HOW-TO.
Related
We have a weblogic application that needs to support being served from multiple domains (e.g. "foo.com" and "bar.com"). Once a user initiates a session on one of these domains they can visit to subdomains off that primary domain (e.g. "a.foo.com", "b.foo.com") and share that session across all of these subdomains. If a user jumps from "foo.com" to "bar.com", they will lose their session, which is fine.
We were able to successfully implement this on JBoss/Tomcat by customizing a 'Valve' to rewrite the session cookie to always be at the top level domain for the serverName that is being requested (i.e. request.getServerName()).
However, we are currently in the process of migrating our application from JBoss to Weblogic and are trying to figure out how to support the same requirement. We have found that weblogic does allow for sharing sessions across multiple subdomains of a single domain by setting the 'cookie-domain' property within the weblogic.xml:
<session-descriptor>
<cookie-path>/store</cookie-path >
<cookie-domain>.foo.com</cookie-domain>
</session-descriptor>
However, we haven't figured out how to configure support for multiple domains (i.e. both foo.com and bar.com). From what we can tell, the weblogic.xml file doesn't support this.
If we only configure one of the domains in the weblogic.xml, sessions do not work properly for the domain that is not configured (i.e. every request leads to a new session).
Any ideas on how we can support sessions across different domains for a single web-app on weblogic?
We are running on Weblogic 12c.
As of WebLogic 12c, Oracle confirmed that what we were trying to do is not currently supported. There are also no immediate plans to implement such a feature.
The workaround that we chose to implement was to use mod_rewrite to rewrite the domain of the JSESSIONID cookie at the HTTP server level to be the domain of the request.
I believe such an option should NOT be supported. If it is allowed then nothing prevents hotmail.com from configuring yahoo.com (say) in its configuration file and getting access to yahoo's JSESSIONID value.
General Case: A simple application that exposes its services through EJB (3.1) - most of them Stateless Sessions beans (nothing funcy here) and SWING based clients that, call through remote interfaces these services and do what they have to do.
Security: I want to authenticate/authorize this cycle of calls and of course protect my services. The obvious answer would be to use JAAS in the server and any custom wiring setup on the underlying server. That is still an option
Apache Shiro: So lots of people talk about Apache Shiro and indeed it features a very simple API and mechanism - that could potentially be application server independent.
Technical Questions:
Session: In my case I dont have an HTTP session - and from what I have understood Shiro at least needs some sort of SESSION ID that I need to pass around. Any nice way on injecting user credentials in my RMI/IIOP calls to the server with not polluting my business API?
Server side implementation: For the few resources I have gone through I think I can implement a Shiro DefaultSecurityManager by 'referencing it' from a Singleton Ejb 3.1 bean. Any other ideas?
Then I can easily create an interceptor and add it to my remote calls - so when a new call is going through my Remote EJB method - the Shiro Intereceptor to validate my user or check for specific rights.
Any comments/ tips / examples ?
Many thanks
From shiro, try to use a ServiceLocator pattern. The lookup of EJB is different between containers (JBoss, Netweaver, Weblogig, etc).
In Application Server, try to use the the container based constraints of security (#RolesAllowed, #PermitAll, #Deny...). JAAS will create the subject with principals of user, so just use the container authorization (#RolesAllowed, #PermitAll, #Deny...). Can be better when you migrate from one container to other.
I'm trying to understand how the JAAS principal propagates to the Business/EJB tier from web tier.
I've read that the if the roles/realm is configured in login-config & security-context of web.xml then the servlet container will also transparently pass the authenticated principal to the EJB Tier.
Two questions
1.) First & more importantly is that true ? Without any intervention from the developer !
2.) And secondly any idea how that works under the hood.
yes it's true. that's generally the point of ejb, to take the "hard" stuff out of the hands of the developer (e.g. security, transactions, robustness, multithreading, etc.)
it's implementation dependent. i know that in jboss (at least 4.x and before), remote method calls used a custom serialization protocol which had an additional Map of arbitrary information which could be sent along with the request. in this was the auth info as well as other stuff to support clustering. for local method calls i believe they use stuff like ThreadLocals.
There are various "context" pieces of information that get propagated in EJB calls, once you get inside the EJB layer and start doing EJB-EJB calls then Transactions would be an example. Some containers allow you to create your own such context objects too.
Thread-local storage can be used within a process, but generally just assume that the container is in charge and can do the right thing - the actual technique is implementation specific.
Regarding your first question - yes.
Regarding your second question - are you familiar for example with EJB3 interceptors?
The container create proxied objects with "interception code" for the beans,
and in addition the container can track other annotations on the methods and the bean class, for example, to detect the #PostConstruct annotation.
Using the role definition, it can check the configuration (either login-config.xml at older versions of jboss, or standalone.xml in JBoss AS 7 at standalone configuration) and understand what is the definition per each role.
JAAS is used in order to provide you abstraction layer over authentication and authorization.
One of the concepts behind JAAS is login module - it provides you "protocol specific" code that takes care of the actual authorization and authentication.
For example, I'm using in this way Krb5LoginModule to use kerberos.
The Principal propagates to the EJB tier from web tier is configured through the login-config in the web.xml as you had surmised for the most part.
How it is implemented is implementation dependent. The user/group data is also implementation dependent and is configured as part of the application server.
However, one of they ways this is done is through an implementation of the JASPIC provider which is a standard way of obtaining the Principal. Using this allows you to have a different authentication path compared to the standard form login, basic authentication or certificate authentication provided by WEB-INF/web.xml but it is a little bit more work.
JASPIC authentication paths allow more complex scenarios such as header based authentication or two-factor or OpenID. The user database "usually" does not need to be tied to the one in the application server. I say "usually" because WebSphere Application Server ties the authentication to a user configured on the server.
I have been trying to figure out a way to create shared Hibernate session service on Tomcat 6.
basically, I need to have this service: 1. to be re-deployable (which exclude the JNDI service); 2. all the web applications can share the same Hibernate sessions (cache). The Tomcat class loading mechanism seems make sharing the db sessions impossible. I could create a web application with the Spring HttpInvoker which can be used by other web applications. Or I could go with the Spring dm-Server but it seems the complexity of the solution would comparable to that of an application server (JBoss or Glassfish).
What would be the viable solution?
You can use the 2nd level cache
Apart from that - let's assume you want to modularize you application and that's the reason for having two (or more) webapps. But if you want to cache entities from two different webapps, that means the same entity classes exist in both. Which by itself isn't that wrong, but having the same cache for these entities in different contexts seems wrong. Perhaps you don't need two web apps after all?
If you are certain that you need this, you can try implementing a custom Tomcat valve, but I can give you neither recommendations nor details about it.
I'm having an inconvenient dealing with sessions..
I have this:
www.mydomain.com
sub1.mydomain.com
sub2.mydomain.com
sub3.mydomain.com
and when I log into "www", then I change to "sub2" (for example) I
figure out it creates another session :S
why is that??
I need the same session for www, sub1, sub2, sub3, and so on.. ALL in
"mydomain.com"..
what can I do?? is it like that and I have to make a trick?? or is
there a "legal" solution for what I want??
The JSESSIONID cookie is issued by the container, and the cookie domain and path is always that of the web application's domain and context root.
It appears as if you have multiple applications in which case, the JSESSIONID issued by one application will not be recognized by another, due to a change in either the domain or the context root, even if the applications are in the same container.
There are multiple ways to deal with this:
If you are not dealing with a high-value application, and if you can guarantee that no 'rogue' applications will be deployed on the server, you can configure the server to share sessions across applications. Weblogic Server can be configured to do this.
Use a central authentication and session management provider - SSO.
Use TLS/SSL - most servers do not issue a JSESSIONID cookie when communication is over SSL, and instead use SSL itself to store state. You will have mixed results here.
Update:
Glassfish v3 allows you to set the domain for the session cookie. This is done via the session-config element in sun-web.xml. I'm not sure if this is available in v2 or lower versions of Glassfish.
Yes, it is like that because you will have separate session cookie for every different domain. Which web server do you use ? You may implement SSO related solution to share data across the domains.
Look at this tutorial: http://javadude.wordpress.com/2011/05/12/glassfish-3-1-%e2%80%93-clustering-tutorial-part2-sessions/
I summarized all steps for Glassfish 3.1 and session replication