Java – single sign on jetty with multiple webappcontext instances

I have an embedded jetty server that iterates over a list of webapps from many different locations (between different deployments) I'm trying to switch from basic authentication to form authentication

What I want to do is:

// create constraint
Constraint usersOnly = new Constraint(Constraint.__FORM_AUTH,"user");
usersOnly.setAuthenticate(true);
ConstraintMapping requireAuthentication = new ConstraintMapping();
requireAuthentication.setConstraint(usersOnly);
requireAuthentication.setPathSpec("/*");

// create login service
LoginService loginService = new HashLoginService("realm");
loginService.setConfig("users.txt");

// create form authentication
FormAuthenticator formAuthenticator = new FormAuthenticator("/login","/login",true);

// create /login route
ServletHolder loginServlet = new ServletHolder(new DefaultServlet() {
@Override
  protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
    response.getWriter().append("<html>\n<head>\n<title>Login</title>\n</head>\n<body>\n"
    + "<form method='POST' action='/j_security_check'>\n"
    + "<input type='text' name='j_username'/>\n"
    + "<input type='password' name='j_password'/>\n"
    + "<input type='submit' value='Login'/>\n</form>\n</body>\n</html>\n");
  }
});

ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.addMapping(requireAuthentication);
securityHandler.setLoginService(loginService);
securityHandler.setAuthenticator(formAuthenticator);

// assign security to each webapp
for (WebAppContext webapp : webapps) {
  webapp.setSecurityHandler(securityHandler);
  webapp.addServlet(loginServlet,"/login");
}

If there is only one webapp in webapps, it can work normally, but if there are multiple webapps, you will be prompted to log in every time you track the link from one webapp to another, and will be redirected to the underlying webapp every time you re authenticate Route '/' and authenticate only for that route

I want my background to share the conversation

According to this question, configuring a public SessionManager for each webappcontext instance should solve the problem, but asker has only one webappcontext instance If I try to assign the same SessionManager instance to each webappcontext, I will get NPE

I also see that some resources point to setting the path of sessioncookeieconfig of each context as the public context path and setting userequestedd as true of SessionManager of each webappcontext, but this solution is applicable to org mortbay. Jetty and out of date

If you have any insights or experience in setting up SSO for embedded jetty servers with multiple webappcontexts, or if you can think of a better way to use a common server to provide multiple different web applications, please point out my right direction

How to allow users to authenticate all web applications processed by one server by filling out a single form?

If I don't know or you have any questions, please let me know

Solution

My solution is to extend the hashsessionmanager class to query sessionidmanager before creating a new session The result is that the crosscontextsessionmanager instance under the same sessionidmanager shares the session content, not just the session ID. therefore, logging in to a webapp means logging in all

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;
  }
}

If the request already carries an ID, newsessionid will only extract the ID. otherwise, it will create a unique new ID from all existing IDs

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>