2011-08-12 2 views
4

http://mydomain.comhttp://www.mydomain.com으로 이동하는 사용자가 http://subdomain.mydomain.com에 대한 요청에 대해 세션 쿠키를 사용할 수 있도록 Tomcat에서 SSO를 사용하도록 설정하려고합니다. 세 도메인 모두 동일한 webapp로 이동하므로 SSO를 전혀 사용하지 않고 표준 JSESSIONID 쿠키로 도메인을 설정하는 것이 이상적입니다.Tomcat - 영역이없는 SSO?

그러나 그럴 가능성이 없어서 Tomcat의 SSO 밸브를 활성화하려고합니다. 문제는 Valve가 영역 정의를 필요로하고 영역이 사용자와 역할 데이터베이스를 지정해야한다는 것입니다. 그러나 컨테이너 기반 인증이나 역할 기반 권한 부여를 사용하지 않으므로 영역을 구성 할 필요가 없거나 구성하려고합니다. 내가 원하는 것은 각각의 다른 하위 도메인에서 세션 쿠키를 공유 할 수 있기를 바랍니다.

이 작업을 수행하는 간단한 방법이 있습니까?

편집이에 대한 나의 현재 해결 방법은 서버에서 "표준"서버 이름에 들어오는 모든 요청을 리디렉션하는 것입니다

. 이것은 충분히 잘 작동하지만 분명히 실제로 문제를 해결하는 것은 아닙니다.

답변

2

동일한 문제가 발생하여 Cookie 세션의 도메인 부분을 덮어 쓰거나 설정하는 Tomcat Valve을 만들었습니다. 아주 간단하고 이미 수년 동안 작동합니다. '.'세션이 새로운 경우에만 - - - - - 요청 된 호스트 이름 를 가져옵니다 - 세션 쿠키 찾을 수있는 호스트 이름을 분할을 :

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

그냥 시도해보세요. 쉬워야합니다. –