Tomcat - SSO without a kingdom?

I am trying to enable SSO under Tomcat so that users who go to http://mydomain.com and http://www.mydomain.com will have their session cookie for requests made at http://subdomain.mydomain.com . All three of these domains go to the same webapp, so ideally I would not contact SSO at all and just set the domain in the standard JSESSIONID cookie.

However, this is not possible, so I am trying to enable Tomcat SSO Valve. The problem is that Valve requires a definition of Realm, and Realm must specify a database of users and roles. However, I do not use container-based authentication and role-based authentication, so I do not need or need to configure Realm. All I want is session cookies, which can be shared between each of these different subdomains.

Is there an easy way to do this?

Edit

My current workaround for this is to redirect the server to each incoming request in the name of the "canonical" server. This works quite well, but obviously this is actually not a solution to the problem.

+4
source share
1 answer

We had the same problem and created Tomcat Valve that would replace or set part of a domain in a Cookie session. A simple thing, and it has been working for many years. The code is as follows:

 public class CrossSubdomainSessionValve extends ValveBase { public CrossSubdomainSessionValve() { super(); info = "common-tomcat-CrossSubdomainSessionValve"; } @Override public void invoke(Request request, Response response) throws IOException, ServletException { // cookie will only need to be changed, if this session is created by this request. if (request.getSession(true).isNew()) { Cookie sessionCookie = findSessionCookie(response.getCookies()); if (sessionCookie != null) { String cookieDomainToSet = getCookieDomainToSet(request.getServerName()); if (cookieDomainToSet != null) { // changing the cookie only does not help, because tomcat immediately sets // a string representation of this cookie as MimeHeader, thus we also // have to change this representation replaceCookie(response.getCoyoteResponse().getMimeHeaders(), sessionCookie, cookieDomainToSet); } } } // process the next valve getNext().invoke(request, response); } protected Cookie findSessionCookie(Cookie[] cookies) { if (cookies != null) for (Cookie cookie : cookies) if (Globals.SESSION_COOKIE_NAME.equals(cookie.getName())) { return cookie; return null; } protected void replaceCookie(MimeHeaders headers, Cookie originalCookie, String domainToSet) { // if the response has already been committed, our replacementstrategy will have no effect // find the Set-Cookie header for the existing cookie and replace its value with new cookie for (int i = 0, size = headers.size(); i < size; i++) { if (headers.getName(i).equals("Set-Cookie")) { MessageBytes value = headers.getValue(i); if (value.indexOf(originalCookie.getName()) >= 0) { if (originalCookie.getDomain() == null) { StringBuilder builder = new StringBuilder(value.getString()).append("; Domain=").append(domainToSet); value.setString(builder.toString()); } else { String newDomain = value.getString().replaceAll("Domain=[A-Za-z0-9.-]*", "Domain=" + domainToSet); value.setString(newDomain); } } } } } protected String getCookieDomainToSet(String cookieDomain) { String[] parts = cookieDomain.split("\\."); if (parts.length >= 3) { return "." + parts[parts.length - 2] + "." + parts[parts.length - 1]; } return null; } public String toString() { return ("CrossSubdomainSessionValve[container=" + container.getName() + ']'); } } 

The algorithm works as follows: - Only if the session is new - find the session cookie - Get the requested host name - Divide the host name by ".". - If it has at least 3 parts (e.g. www.google.de), delete the first part (in .google.de) - Reset cookie

In a Context configuration, you can apply a valve like this

 <Valve className="my.package.CrossSubdomainSessionValve" httpOnlyEnabled="true" /> 

Caution: in Valve code, a session is created if a session has not been created before, and it does not matter if you need a session at all ...

Hope this helps ... Good luck!

+2
source

All Articles