使用WebAppContext的多个实例单一登录Jetty

时间:2016-03-23 17:07:21

标签: java servlets jetty single-sign-on form-authentication

我有一个嵌入式jetty服务器,它从许多不同的位置迭代一个webapps列表(列表在不同的部署之间)。我试图从基本身份验证过渡到表单身份验证。

我想做的是:

Delegate.GetInvocationList

如果Web应用程序中只有一个webapp,则可以按预期工作,但如果有多个,则每次跟踪从一个Web应用程序到另一个Web应用程序的链接时都会提示您登录,并且每次重新进行身份验证时,在路由" /"重定向到基础webapp;并且仅针对该身份验证。

我想让我的背景分享会话。

根据documentation,为每个WebAppContext实例配置一个公共SessionManager应该可以解决问题,但是asker只有一个WebAppContext实例。如果我尝试将相同的SessionManager实例分配给每个WebAppContext,我会得到NPE。

我还看到一些资源指向将每个上下文的SessionCookieConfig路径设置为公共上下文路径,并将useRequestedId设置为true,以用于每个WebAppContext的SessionManager,但此解决方案适用于组织.mortbay.jetty并且已经过时了。

如果您对具有多个WebAppContexts的嵌入式Jetty服务器设置SSO有任何见解或经验,或者如果您能想到使用一个公共服务器提供多个不同Web应用程序的更好方法,请指出正确的方向。

如何通过填写单个表单,允许用户对一台服务器处理的所有Web应用进行身份验证?

如果我不清楚或者您是否有任何问题,请告诉我。

1 个答案:

答案 0 :(得分:0)

我的解决方案是扩展HashSessionManager类,以便在创建新会话之前查询SessionIdManager。结果是同一个SessionIdManager下的CrossContextSessionManager实例共享会话内容而不仅仅是会话ID。因此,登录一个webapp意味着全部登录。

import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.eclipse.jetty.server.session.AbstractSession;
import org.eclipse.jetty.server.session.HashSessionIdManager;
import org.eclipse.jetty.server.session.HashSessionManager;

/**
 * Allows the WebAppContext to check the server's SessionIdManager before creating a new session
 * so that WebAppContext can share session contents for each client rather than just session ids.
 */
public class CrossContextSessionManager extends HashSessionManager {

  // Number of seconds before the user is automatically logged out of an idle webapp session
  private int defaultSessionTimeout = 1800;

  /**
   * Check for an existing session in the session id manager by the requested id.
   * If no session has that id, create a new HttpSession for the request.
   */
  @Override
  public HttpSession newHttpSession(HttpServletRequest request) {
    AbstractSession session = null;

    String requestedId = request.getRequestedSessionId();
    if (requestedId != null) {
      String clusterId = getSessionIdManager().getClusterId(requestedId);
      Collection<HttpSession> sessions = ((HashSessionIdManager) getSessionIdManager()).getSession(clusterId);
      for (HttpSession httpSession : sessions) {
        session = (AbstractSession) httpSession;
        break;
      }
    }

    if (session == null) {
      session = newSession(request);
      session.setMaxInactiveInterval(defaultSessionTimeout);
      addSession(session,true);
    }

    return session;
  }
}

如果请求已经携带了id,则newSessionId将从中提取该id。否则,它将创建一个与所有现有ID唯一的新ID。