2011-08-12 8 views
4

私はhttp://mydomain.comhttp://www.mydomain.comに行くユーザーがhttp://subdomain.mydomain.comに行われたリクエストに対してセッションクッキーを利用できるように、Tomcatの下でSSOを有効にしようとしています。これら3つのドメインはすべて同じwebappに行きますので、理想的にはSSOを混乱させずに、標準のJSESSIONIDクッキーにドメインを設定したいと思います。Tomcat - RealmなしのSSO?

しかし、そうは思わしくないので、TomcatのSSOバルブを有効にしようとしています。問題は、バルブがレルムの定義を必要とし、レルムがユーザーとロールのデータベースを指定することになっていることです。しかし、私はコンテナベースの認証も役割ベースの認証も使用していないため、レルムを設定する必要はありません。私が望むのは、セッションクッキーをこれらの異なるサブドメインのそれぞれで共有できることだけです。

これを行う簡単な方法はありますか?

編集

このため私の現在の回避策は、サーバーが「正規」サーバー名へのすべての着信要求をリダイレクトすることです。これは十分に機能しますが、明らかに問題を実際に解決するわけではありません。

答えて

2

同じ問題が発生し、セッションのドメイン部分を上書きまたは設定するTomcat Valveを作成しましたCookieかなりシンプルなもので、すでに何年も働いています。 「」セッションが新しい場合のみ - - - 要求されたホスト名 を取得する - セッションクッキー 見つけるとホスト名を分割し :

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() + ']'); 
    } 
} 

アルゴリズムは次のように動作します。コードは次のようになります - それは(www.google.deのような)少なくとも3つの部分を持っている場合は、最初の部分を削除する(.google.deする) - あなたのコンテキストの設定でクッキー

をリセットしますが、この

のようにバルブを適用することができます
<Valve className="my.package.CrossSubdomainSessionValve" httpOnlyEnabled="true" /> 

警告:コードでValveにはセッションが前に作成されなかった場合は、セッションを作成し、まったくのセッションが必要な場合は気にしない...

希望に役立ちます...幸運を!

+0

ありがとう、私はこれを試してみましょう。 'Valve'が' Context'で定義されている必要がありますか、あるいは 'Host'設定の一部として行うことができますか? – aroth

+0

ちょうどそれを試してみてください、簡単にする必要があります –