The only way i was able to get around this was to write my own FormAuthenticator and register it with tomcat.
with the default authenticator you are also not allowed to hit the login page directly (does a response.sendError() if there is no destination url saved), and it's not very good at flushing the user (if you login, then get to the login page again and login as a diff user without logging out, you will still be running as the previous user). you can get around all this stuff if you just modify the default FormAuthenticator. here are my modifications, noted with /** CHANGE **/ comments... Also, i make the assumption that if there was no saved requestURI then redirect to the context root... this way the configured welcome page will be displayed. | public class FormAuthenticator | extends org.jboss.web.tomcat.tc4.authenticator.FormAuthenticator | { | | /** | * Authenticate the user making this request, based on the specified | * login configuration. Return <code>true</code> if any specified | * constraint has been satisfied, or <code>false</code> if we have | * created a response challenge already. | * <p> | * Differs from the standard Tomcat version in if no <code>Principal</code> | * has already been authenticated to the request, method still checks | * if <code>SingleSignOn</code> has set an SSO_ID note on the request. | * <code>SingleSignOn</code> may do this if the single sign-on session | * was created by an application using CERT or DIGEST authentication. | * If it has, the note is removed so that when this authenticator registers | * its authentication, a new single sign-on session will be created. | * | * @param request Request we are processing | * @param response Response we are creating | * @param config Login configuration describing how authentication | * should be performed | * | * @exception IOException if an input/output error occurs | */ | public boolean authenticate( | HttpRequest request, | HttpResponse response, | LoginConfig config) | throws IOException | { | Logger.trace.enter(FormAuthenticator.class, "authenticate()"); | | HttpServletRequest hreq = | (HttpServletRequest) request.getRequest(); | | // Have we already authenticated someone? | // Note: SingleSignOn does not call setUserPrincipal(), | // so whoever did it would have to be some custom valve | // in the pipeline | Principal principal = hreq.getUserPrincipal(); | String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); | if (principal != null) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Found principal '" + principal.getName() + "'"); | // Associate the session with any existing SSO session | if (ssoId != null) | associate(ssoId, getSession(request, true)); | | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return true; | } | | // Is there an SSO session against which we can try to reauthenticate? | if (ssoId != null) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "SSO Id set"); | // Try to reauthenticate using data cached by SSO. If this fails, | // either the original SSO logon was of DIGEST or SSL (which | // we can't reauthenticate ourselves because there is no | // cached username and password), or the realm denied | // the user's reauthentication for some reason. | // In either case we have to prompt the user for a logon | if (reauthenticateFromSSO(ssoId, request)) | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return true; | } | | // References to objects we will need later | HttpServletResponse hres = | (HttpServletResponse) response.getResponse(); | Session session = null; | | // Have we authenticated this user before but have caching disabled? | if (!cache) | { | session = getSession(request, true); | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Checking for reauthenticate in session " + session); | String username = | (String) session.getNote(Constants.SESS_USERNAME_NOTE); | String password = | (String) session.getNote(Constants.SESS_PASSWORD_NOTE); | if ((username != null) && (password != null)) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Reauthenticating username '" + username + "'"); | | /** CHANGE **/ | String newUsername = hreq.getParameter(Constants.FORM_USERNAME); | String newPassword = hreq.getParameter(Constants.FORM_PASSWORD); | | // if newUsername is not null, then the user just came from | // the login page... so flush the user and re-authenticate. | if(newUsername != null){ | // flush the old user out. | flushAuthCache(username); | | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Authenticating new username '" + newUsername + "'"); | | // authenticate user. | principal = context.getRealm().authenticate( | newUsername, newPassword); | | session.setNote(Constants.SESS_USERNAME_NOTE, newUsername); | session.setNote(Constants.SESS_PASSWORD_NOTE, newPassword); | }else{ | // same user... authenticate them as usual. | principal = context.getRealm().authenticate( | username, password); | } | | if (principal != null) | { | session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); | register(request, response, principal, | Constants.FORM_METHOD, | newUsername, newPassword); | | // if user went back to login page in same session, the | // the request url will be '/j_security_check' which will | // result in 404. So redirect to root (should send to welcome | // file). | if(Constants.FORM_ACTION.equals(hreq.getServletPath())){ | String requestURI = "/"; | /*requestURI = hreq.getContextPath(); | if(!requestURI.startsWith("/")){ | requestURI = "/" + requestURI; | }*/ | //hres.sendRedirect(hres.encodeRedirectURL(requestURI)); | try{ | hreq.getRequestDispatcher(requestURI).forward(hreq, hres); | }catch(ServletException se){ | throw new IOException(se.getMessage()); | } | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (false); | } | | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (true); | } | /** CHANGE_ORGIGINAL | principal = | context.getRealm().authenticate(username, password); | if (principal != null) | { | session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); | register(request, response, principal, | Constants.FORM_METHOD, | newUsername, newPassword); | return (true); | } | /** END CHANGE **/ | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Reauthentication failed, proceed normally"); | } | } | | // Is this the re-submit of the original request URI after successful | // authentication? If so, forward the *original* request instead. | if (matchRequest(request)) | { | session = getSession(request, true); | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Restore request from session '" + session.getId() + "'"); | principal = (Principal) | session.getNote(Constants.FORM_PRINCIPAL_NOTE); | register(request, response, principal, Constants.FORM_METHOD, | (String) session.getNote(Constants.SESS_USERNAME_NOTE), | (String) session.getNote(Constants.SESS_PASSWORD_NOTE)); | ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); | if (ssoId != null) | associate(ssoId, session); | if (restoreRequest(request, session)) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Proceed to restored request"); | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (true); | } | else | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Restore of original request failed"); | hres.sendError(HttpServletResponse.SC_BAD_REQUEST); | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (false); | } | } | | // Acquire references to objects we will need to evaluate | String contextPath = hreq.getContextPath(); | String requestURI = request.getDecodedRequestURI(); | response.setContext(request.getContext()); | | // Is this a request for the login page itself? Test here to avoid | // displaying it twice (from the user's perspective) -- once because | // of the "save and redirect" and once because of the "restore and | // redirect" performed below. | /** CHANGE **/ | String loginURI = config.getLoginPage(); | /** CHANGE_ORIGINAL | String loginURI = contextPath + config.getLoginPage(); | /** END CHANGE **/ | if (requestURI.equals(loginURI)) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Requesting login page normally"); | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (true); // Display the login page in the usual manner | } | | // Is this a request for the error page itself? Test here to avoid | // an endless loop (back to the login page) if the error page is | // within the protected area of our security constraint | String errorURI = config.getErrorPage(); | if (requestURI.equals(errorURI)) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Requesting error page normally"); | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (true); // Display the error page in the usual manner | } | | // Is this the action request from the login page? | boolean loginAction = | requestURI.startsWith(contextPath) && | requestURI.endsWith(Constants.FORM_ACTION); | | // No -- Save this request and redirect to the form login page | if (!loginAction) | { | session = getSession(request, true); | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Save request in session '" + session.getId() + "'"); | saveRequest(request, session); | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Redirect to login page '" + loginURI + "'"); | //hres.sendRedirect(hres.encodeRedirectURL(loginURI)); | try{ | hreq.getRequestDispatcher(loginURI).forward(hreq, hres); | }catch(ServletException se){ | throw new IOException(se.getMessage()); | } | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (false); | } | | // Yes -- Validate the specified credentials and redirect | // to the error page if they are not correct | Realm realm = context.getRealm(); | String username = hreq.getParameter(Constants.FORM_USERNAME); | String password = hreq.getParameter(Constants.FORM_PASSWORD); | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Authenticating username '" + username + "'"); | /** CHANGE **/ | // flush the user from the auth cache first. | flushAuthCache(username); | /** END CHANGE **/ | principal = realm.authenticate(username, password); | | if (principal == null) | { | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Redirect to error page '" + errorURI + "'"); | //hres.sendRedirect(hres.encodeRedirectURL(errorURI)); | try{ | hreq.getRequestDispatcher(errorURI).forward(hreq, hres); | }catch(ServletException se){ | throw new IOException(se.getMessage()); | } | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (false); | } | | // Save the authenticated Principal in our session | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Authentication of '" + username + "' was successful"); | if (session == null) | session = getSession(request, true); | session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); | | // If we are not caching, save the username and password as well | if (!cache) | { | session.setNote(Constants.SESS_USERNAME_NOTE, username); | session.setNote(Constants.SESS_PASSWORD_NOTE, password); | } | | // Redirect the user to the original request URI (which will cause | // the original request to be restored) | requestURI = savedRequestURL(session); | /** CHANGE **/ | if (requestURI == null){ | //requestURI = "/"; | requestURI = hreq.getContextPath(); | if(!requestURI.startsWith("/")){ | requestURI = "/" + requestURI; | } | } | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Redirecting to '" + requestURI + "'"); | | // redirect ensures that servlet filters can be run. | hres.sendRedirect(hres.encodeRedirectURL(requestURI)); | /*try{ | hreq.getRequestDispatcher(requestURI).forward(hreq, hres); | }catch(ServletException se){ | throw new IOException(se.getMessage()); | }*/ | /** CHANGE_ORIGINAL | if (Logger.trace.isEnabled(FormAuthenticator.class)) | Logger.trace.debug(FormAuthenticator.class, | "authenticate()", | "Redirecting to original '" + requestURI + "'"); | | if (requestURI == null) | hres.sendError(HttpServletResponse.SC_BAD_REQUEST, | sm.getString("authenticator.formlogin")); | else | hres.sendRedirect(hres.encodeRedirectURL(requestURI)); | /** END CHANGE **/ | Logger.trace.exit(FormAuthenticator.class, "authenticate()"); | return (false); | | } | | /** | * Save the original request information into our session. | * | * @param request The request to be saved | * @param session The session to contain the saved information | */ | private void saveRequest(HttpRequest request, Session session) | { | | // Create and populate a SavedRequest object for this request | HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); | SavedRequest saved = new SavedRequest(); | Cookie cookies[] = hreq.getCookies(); | if (cookies != null) | { | for (int i = 0; i < cookies.length; i++) | saved.addCookie(cookies); | } | Enumeration names = hreq.getHeaderNames(); | while (names.hasMoreElements()) | { | String name = (String) names.nextElement(); | Enumeration values = hreq.getHeaders(name); | while (values.hasMoreElements()) | { | String value = (String) values.nextElement(); | saved.addHeader(name, value); | } | } | Enumeration locales = hreq.getLocales(); | while (locales.hasMoreElements()) | { | Locale locale = (Locale) locales.nextElement(); | saved.addLocale(locale); | } | Map parameters = hreq.getParameterMap(); | Iterator paramNames = parameters.keySet().iterator(); | while (paramNames.hasNext()) | { | String paramName = (String) paramNames.next(); | String paramValues[] = (String[]) parameters.get(paramName); | saved.addParameter(paramName, paramValues); | } | saved.setMethod(hreq.getMethod()); | saved.setQueryString(hreq.getQueryString()); | saved.setRequestURI(hreq.getRequestURI()); | | // Stash the SavedRequest in our session for later use | session.setNote(Constants.FORM_REQUEST_NOTE, saved); | | if(Logger.trace.isEnabled(FormAuthenticator.class)){ | Logger.trace.debug(FormAuthenticator.class, | "saveRequest()", | "Saved uri: " + savedRequestURL(session)); | } | } | | | /** | * Return the request URI (with the corresponding query string, if any) | * from the saved request so that we can redirect to it. | * | * @param session Our current session | */ | private String savedRequestURL(Session session) | { | | SavedRequest saved = | (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE); | if (saved == null) | return (null); | StringBuffer sb = new StringBuffer(saved.getRequestURI()); | if (saved.getQueryString() != null) | { | sb.append('?'); | sb.append(saved.getQueryString()); | } | return (sb.toString()); | | } | | /** CHANGE (added) **/ | /** | * Flushes the user with the supplied username from the cache. | * | * @param _username The username of the user to flush. | */ | private void flushAuthCache(String _username) | { | try{ | // get security context to lookup domain from. | InitialContext context = new InitialContext(); | Context securityCtx = (Context) context.lookup("java:comp/env/security"); | | // get security manager. | JaasSecurityManager securityMgr = (JaasSecurityManager) | securityCtx.lookup("securityMgr"); | | // get domain. | String domain = securityMgr.getSecurityDomain(); | | Logger.trace.debug(FormAuthenticator.class, | "flushAuthCache()", | "Flushing user '" + _username + "' from domain cache '" + domain + "'"); | | // get rmi adapter to invoke security mbean with. | String connectorName = "jmx/invoker/RMIAdaptor"; | RMIAdaptor server = (RMIAdaptor) context.lookup(connectorName); | | // invoke the security mbean. | ObjectName jaasMgr = new ObjectName( | "jboss.security:service=JaasSecurityManager"); | Object[] params = {domain, new SimplePrincipal(_username)}; | String[] signature = {"java.lang.String","java.security.Principal"}; | server.invoke(jaasMgr, "flushAuthenticationCache", params, signature); | | }catch(Exception e){ | Logger.error.caught(FormAuthenticator.class, "flushAuthCache()", e); | } | } | /** END CHANGE (added) **/ | } | View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3835867#3835867 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3835867 ------------------------------------------------------- This SF.Net email is sponsored by: Oracle 10g Get certified on the hottest thing ever to hit the market... Oracle 10g. Take an Oracle 10g class now, and we'll give you the exam FREE. http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click _______________________________________________ JBoss-user mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-user