Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » authenticator » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.authenticator;
   20   
   21   
   22   import java.io.IOException;
   23   import java.security.MessageDigest;
   24   import java.security.NoSuchAlgorithmException;
   25   import java.security.Principal;
   26   import java.text.SimpleDateFormat;
   27   import java.util.Date;
   28   import java.util.Locale;
   29   import java.util.Random;
   30   
   31   import javax.servlet.ServletException;
   32   import javax.servlet.http.Cookie;
   33   
   34   import org.apache.catalina.Authenticator;
   35   import org.apache.catalina.Container;
   36   import org.apache.catalina.Context;
   37   import org.apache.catalina.Lifecycle;
   38   import org.apache.catalina.LifecycleException;
   39   import org.apache.catalina.LifecycleListener;
   40   import org.apache.catalina.Manager;
   41   import org.apache.catalina.Pipeline;
   42   import org.apache.catalina.Realm;
   43   import org.apache.catalina.Session;
   44   import org.apache.catalina.Valve;
   45   import org.apache.catalina.connector.Request;
   46   import org.apache.catalina.connector.Response;
   47   import org.apache.catalina.deploy.LoginConfig;
   48   import org.apache.catalina.deploy.SecurityConstraint;
   49   import org.apache.catalina.util.DateTool;
   50   import org.apache.catalina.util.LifecycleSupport;
   51   import org.apache.catalina.util.StringManager;
   52   import org.apache.catalina.valves.ValveBase;
   53   import org.apache.juli.logging.Log;
   54   import org.apache.juli.logging.LogFactory;
   55   
   56   
   57   /**
   58    * Basic implementation of the <b>Valve</b> interface that enforces the
   59    * <code>&lt;security-constraint&gt;</code> elements in the web application
   60    * deployment descriptor.  This functionality is implemented as a Valve
   61    * so that it can be ommitted in environments that do not require these
   62    * features.  Individual implementations of each supported authentication
   63    * method can subclass this base class as required.
   64    * <p>
   65    * <b>USAGE CONSTRAINT</b>:  When this class is utilized, the Context to
   66    * which it is attached (or a parent Container in a hierarchy) must have an
   67    * associated Realm that can be used for authenticating users and enumerating
   68    * the roles to which they have been assigned.
   69    * <p>
   70    * <b>USAGE CONSTRAINT</b>:  This Valve is only useful when processing HTTP
   71    * requests.  Requests of any other type will simply be passed through.
   72    *
   73    * @author Craig R. McClanahan
   74    * @version $Revision: 892545 $ $Date: 2009-12-20 02:04:17 +0100 (Sun, 20 Dec 2009) $
   75    */
   76   
   77   
   78   public abstract class AuthenticatorBase
   79       extends ValveBase
   80       implements Authenticator, Lifecycle {
   81       private static Log log = LogFactory.getLog(AuthenticatorBase.class);
   82   
   83   
   84       // ----------------------------------------------------- Instance Variables
   85   
   86   
   87       /**
   88        * The default message digest algorithm to use if we cannot use
   89        * the requested one.
   90        */
   91       protected static final String DEFAULT_ALGORITHM = "MD5";
   92   
   93   
   94       /**
   95        * The number of random bytes to include when generating a
   96        * session identifier.
   97        */
   98       protected static final int SESSION_ID_BYTES = 16;
   99   
  100   
  101       /**
  102        * The message digest algorithm to be used when generating session
  103        * identifiers.  This must be an algorithm supported by the
  104        * <code>java.security.MessageDigest</code> class on your platform.
  105        */
  106       protected String algorithm = DEFAULT_ALGORITHM;
  107   
  108   
  109       /**
  110        * Should we cache authenticated Principals if the request is part of
  111        * an HTTP session?
  112        */
  113       protected boolean cache = true;
  114   
  115   
  116       /**
  117        * Should the session ID, if any, be changed upon a successful
  118        * authentication to prevent a session fixation attack?
  119        */
  120       protected boolean changeSessionIdOnAuthentication = true;
  121       
  122       /**
  123        * The Context to which this Valve is attached.
  124        */
  125       protected Context context = null;
  126   
  127   
  128       /**
  129        * Return the MessageDigest implementation to be used when
  130        * creating session identifiers.
  131        */
  132       protected MessageDigest digest = null;
  133   
  134   
  135       /**
  136        * A String initialization parameter used to increase the entropy of
  137        * the initialization of our random number generator.
  138        */
  139       protected String entropy = null;
  140   
  141   
  142       /**
  143        * Descriptive information about this implementation.
  144        */
  145       protected static final String info =
  146           "org.apache.catalina.authenticator.AuthenticatorBase/1.0";
  147   
  148       /**
  149        * Flag to determine if we disable proxy caching, or leave the issue
  150        * up to the webapp developer.
  151        */
  152       protected boolean disableProxyCaching = true;
  153   
  154       /**
  155        * Flag to determine if we disable proxy caching with headers incompatible
  156        * with IE 
  157        */
  158       protected boolean securePagesWithPragma = true;
  159       
  160       /**
  161        * The lifecycle event support for this component.
  162        */
  163       protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  164   
  165   
  166       /**
  167        * A random number generator to use when generating session identifiers.
  168        */
  169       protected Random random = null;
  170   
  171   
  172       /**
  173        * The Java class name of the random number generator class to be used
  174        * when generating session identifiers.
  175        */
  176       protected String randomClass = "java.security.SecureRandom";
  177   
  178   
  179       /**
  180        * The string manager for this package.
  181        */
  182       protected static final StringManager sm =
  183           StringManager.getManager(Constants.Package);
  184   
  185   
  186       /**
  187        * The SingleSignOn implementation in our request processing chain,
  188        * if there is one.
  189        */
  190       protected SingleSignOn sso = null;
  191   
  192   
  193       /**
  194        * Has this component been started?
  195        */
  196       protected boolean started = false;
  197   
  198   
  199       /**
  200        * "Expires" header always set to Date(1), so generate once only
  201        */
  202       private static final String DATE_ONE =
  203           (new SimpleDateFormat(DateTool.HTTP_RESPONSE_DATE_HEADER,
  204                                 Locale.US)).format(new Date(1));
  205   
  206   
  207       // ------------------------------------------------------------- Properties
  208   
  209   
  210       /**
  211        * Return the message digest algorithm for this Manager.
  212        */
  213       public String getAlgorithm() {
  214   
  215           return (this.algorithm);
  216   
  217       }
  218   
  219   
  220       /**
  221        * Set the message digest algorithm for this Manager.
  222        *
  223        * @param algorithm The new message digest algorithm
  224        */
  225       public void setAlgorithm(String algorithm) {
  226   
  227           this.algorithm = algorithm;
  228   
  229       }
  230   
  231   
  232       /**
  233        * Return the cache authenticated Principals flag.
  234        */
  235       public boolean getCache() {
  236   
  237           return (this.cache);
  238   
  239       }
  240   
  241   
  242       /**
  243        * Set the cache authenticated Principals flag.
  244        *
  245        * @param cache The new cache flag
  246        */
  247       public void setCache(boolean cache) {
  248   
  249           this.cache = cache;
  250   
  251       }
  252   
  253   
  254       /**
  255        * Return the Container to which this Valve is attached.
  256        */
  257       public Container getContainer() {
  258   
  259           return (this.context);
  260   
  261       }
  262   
  263   
  264       /**
  265        * Set the Container to which this Valve is attached.
  266        *
  267        * @param container The container to which we are attached
  268        */
  269       public void setContainer(Container container) {
  270   
  271           if (!(container instanceof Context))
  272               throw new IllegalArgumentException
  273                   (sm.getString("authenticator.notContext"));
  274   
  275           super.setContainer(container);
  276           this.context = (Context) container;
  277   
  278       }
  279   
  280   
  281       /**
  282        * Return the entropy increaser value, or compute a semi-useful value
  283        * if this String has not yet been set.
  284        */
  285       public String getEntropy() {
  286   
  287           // Calculate a semi-useful value if this has not been set
  288           if (this.entropy == null)
  289               setEntropy(this.toString());
  290   
  291           return (this.entropy);
  292   
  293       }
  294   
  295   
  296       /**
  297        * Set the entropy increaser value.
  298        *
  299        * @param entropy The new entropy increaser value
  300        */
  301       public void setEntropy(String entropy) {
  302   
  303           this.entropy = entropy;
  304   
  305       }
  306   
  307   
  308       /**
  309        * Return descriptive information about this Valve implementation.
  310        */
  311       public String getInfo() {
  312   
  313           return (info);
  314   
  315       }
  316   
  317   
  318       /**
  319        * Return the random number generator class name.
  320        */
  321       public String getRandomClass() {
  322   
  323           return (this.randomClass);
  324   
  325       }
  326   
  327   
  328       /**
  329        * Set the random number generator class name.
  330        *
  331        * @param randomClass The new random number generator class name
  332        */
  333       public void setRandomClass(String randomClass) {
  334   
  335           this.randomClass = randomClass;
  336   
  337       }
  338   
  339       /**
  340        * Return the flag that states if we add headers to disable caching by
  341        * proxies.
  342        */
  343       public boolean getDisableProxyCaching() {
  344           return disableProxyCaching;
  345       }
  346   
  347       /**
  348        * Set the value of the flag that states if we add headers to disable
  349        * caching by proxies.
  350        * @param nocache <code>true</code> if we add headers to disable proxy 
  351        *              caching, <code>false</code> if we leave the headers alone.
  352        */
  353       public void setDisableProxyCaching(boolean nocache) {
  354           disableProxyCaching = nocache;
  355       }
  356       
  357       /**
  358        * Return the flag that states, if proxy caching is disabled, what headers
  359        * we add to disable the caching.
  360        */
  361       public boolean getSecurePagesWithPragma() {
  362           return securePagesWithPragma;
  363       }
  364   
  365       /**
  366        * Set the value of the flag that states what headers we add to disable
  367        * proxy caching.
  368        * @param securePagesWithPragma <code>true</code> if we add headers which 
  369        * are incompatible with downloading office documents in IE under SSL but
  370        * which fix a caching problem in Mozilla.
  371        */
  372       public void setSecurePagesWithPragma(boolean securePagesWithPragma) {
  373           this.securePagesWithPragma = securePagesWithPragma;
  374       }    
  375   
  376       /**
  377        * Return the flag that states if we should change the session ID of an
  378        * existing session upon successful authentication.
  379        * 
  380        * @return <code>true</code> to change session ID upon successful
  381        *         authentication, <code>false</code> to do not perform the change.
  382        */
  383       public boolean getChangeSessionIdOnAuthentication() {
  384           return changeSessionIdOnAuthentication;
  385       }
  386   
  387       /**
  388        * Set the value of the flag that states if we should change the session ID
  389        * of an existing session upon successful authentication.
  390        * 
  391        * @param changeSessionIdOnAuthentication
  392        *            <code>true</code> to change session ID upon successful
  393        *            authentication, <code>false</code> to do not perform the
  394        *            change.
  395        */
  396       public void setChangeSessionIdOnAuthentication(
  397               boolean changeSessionIdOnAuthentication) {
  398           this.changeSessionIdOnAuthentication = changeSessionIdOnAuthentication;
  399       }
  400   
  401       // --------------------------------------------------------- Public Methods
  402   
  403   
  404       /**
  405        * Enforce the security restrictions in the web application deployment
  406        * descriptor of our associated Context.
  407        *
  408        * @param request Request to be processed
  409        * @param response Response to be processed
  410        *
  411        * @exception IOException if an input/output error occurs
  412        * @exception ServletException if thrown by a processing element
  413        */
  414       public void invoke(Request request, Response response)
  415           throws IOException, ServletException {
  416   
  417           if (log.isDebugEnabled())
  418               log.debug("Security checking request " +
  419                   request.getMethod() + " " + request.getRequestURI());
  420           LoginConfig config = this.context.getLoginConfig();
  421   
  422           // Have we got a cached authenticated Principal to record?
  423           if (cache) {
  424               Principal principal = request.getUserPrincipal();
  425               if (principal == null) {
  426                   Session session = request.getSessionInternal(false);
  427                   if (session != null) {
  428                       principal = session.getPrincipal();
  429                       if (principal != null) {
  430                           if (log.isDebugEnabled())
  431                               log.debug("We have cached auth type " +
  432                                   session.getAuthType() +
  433                                   " for principal " +
  434                                   session.getPrincipal());
  435                           request.setAuthType(session.getAuthType());
  436                           request.setUserPrincipal(principal);
  437                       }
  438                   }
  439               }
  440           }
  441   
  442           // Special handling for form-based logins to deal with the case
  443           // where the login form (and therefore the "j_security_check" URI
  444           // to which it submits) might be outside the secured area
  445           String contextPath = this.context.getPath();
  446           String requestURI = request.getDecodedRequestURI();
  447           if (requestURI.startsWith(contextPath) &&
  448               requestURI.endsWith(Constants.FORM_ACTION)) {
  449               if (!authenticate(request, response, config)) {
  450                   if (log.isDebugEnabled())
  451                       log.debug(" Failed authenticate() test ??" + requestURI );
  452                   return;
  453               }
  454           }
  455   
  456           Realm realm = this.context.getRealm();
  457           // Is this request URI subject to a security constraint?
  458           SecurityConstraint [] constraints
  459               = realm.findSecurityConstraints(request, this.context);
  460          
  461           if ((constraints == null) /* &&
  462               (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
  463               if (log.isDebugEnabled())
  464                   log.debug(" Not subject to any constraint");
  465               getNext().invoke(request, response);
  466               return;
  467           }
  468   
  469           // Make sure that constrained resources are not cached by web proxies
  470           // or browsers as caching can provide a security hole
  471           if (disableProxyCaching && 
  472               // FIXME: Disabled for Mozilla FORM support over SSL 
  473               // (improper caching issue)
  474               //!request.isSecure() &&
  475               !"POST".equalsIgnoreCase(request.getMethod())) {
  476               if (securePagesWithPragma) {
  477                   // FIXME: These cause problems with downloading office docs
  478                   // from IE under SSL and may not be needed for newer Mozilla
  479                   // clients.
  480                   response.setHeader("Pragma", "No-cache");
  481                   response.setHeader("Cache-Control", "no-cache");
  482               } else {
  483                   response.setHeader("Cache-Control", "private");
  484               }
  485               response.setHeader("Expires", DATE_ONE);
  486           }
  487   
  488           int i;
  489           // Enforce any user data constraint for this security constraint
  490           if (log.isDebugEnabled()) {
  491               log.debug(" Calling hasUserDataPermission()");
  492           }
  493           if (!realm.hasUserDataPermission(request, response,
  494                                            constraints)) {
  495               if (log.isDebugEnabled()) {
  496                   log.debug(" Failed hasUserDataPermission() test");
  497               }
  498               /*
  499                * ASSERT: Authenticator already set the appropriate
  500                * HTTP status code, so we do not have to do anything special
  501                */
  502               return;
  503           }
  504   
  505           // Since authenticate modifies the response on failure,
  506           // we have to check for allow-from-all first.
  507           boolean authRequired = true;
  508           for(i=0; i < constraints.length && authRequired; i++) {
  509               if(!constraints[i].getAuthConstraint()) {
  510                   authRequired = false;
  511               } else if(!constraints[i].getAllRoles()) {
  512                   String [] roles = constraints[i].findAuthRoles();
  513                   if(roles == null || roles.length == 0) {
  514                       authRequired = false;
  515                   }
  516               }
  517           }
  518                
  519           if(authRequired) {  
  520               if (log.isDebugEnabled()) {
  521                   log.debug(" Calling authenticate()");
  522               }
  523               if (!authenticate(request, response, config)) {
  524                   if (log.isDebugEnabled()) {
  525                       log.debug(" Failed authenticate() test");
  526                   }
  527                   /*
  528                    * ASSERT: Authenticator already set the appropriate
  529                    * HTTP status code, so we do not have to do anything
  530                    * special
  531                    */
  532                   return;
  533               } 
  534               
  535           }
  536       
  537           if (log.isDebugEnabled()) {
  538               log.debug(" Calling accessControl()");
  539           }
  540           if (!realm.hasResourcePermission(request, response,
  541                                            constraints,
  542                                            this.context)) {
  543               if (log.isDebugEnabled()) {
  544                   log.debug(" Failed accessControl() test");
  545               }
  546               /*
  547                * ASSERT: AccessControl method has already set the
  548                * appropriate HTTP status code, so we do not have to do
  549                * anything special
  550                */
  551               return;
  552           }
  553       
  554           // Any and all specified constraints have been satisfied
  555           if (log.isDebugEnabled()) {
  556               log.debug(" Successfully passed all security constraints");
  557           }
  558           getNext().invoke(request, response);
  559   
  560       }
  561   
  562   
  563       // ------------------------------------------------------ Protected Methods
  564   
  565   
  566   
  567   
  568       /**
  569        * Associate the specified single sign on identifier with the
  570        * specified Session.
  571        *
  572        * @param ssoId Single sign on identifier
  573        * @param session Session to be associated
  574        */
  575       protected void associate(String ssoId, Session session) {
  576   
  577           if (sso == null)
  578               return;
  579           sso.associate(ssoId, session);
  580   
  581       }
  582   
  583   
  584       /**
  585        * Authenticate the user making this request, based on the specified
  586        * login configuration.  Return <code>true</code> if any specified
  587        * constraint has been satisfied, or <code>false</code> if we have
  588        * created a response challenge already.
  589        *
  590        * @param request Request we are processing
  591        * @param response Response we are creating
  592        * @param config    Login configuration describing how authentication
  593        *              should be performed
  594        *
  595        * @exception IOException if an input/output error occurs
  596        */
  597       protected abstract boolean authenticate(Request request,
  598                                               Response response,
  599                                               LoginConfig config)
  600           throws IOException;
  601   
  602   
  603       /**
  604        * Generate and return a new session identifier for the cookie that
  605        * identifies an SSO principal.
  606        */
  607       protected synchronized String generateSessionId() {
  608   
  609           // Generate a byte array containing a session identifier
  610           byte bytes[] = new byte[SESSION_ID_BYTES];
  611           getRandom().nextBytes(bytes);
  612           bytes = getDigest().digest(bytes);
  613   
  614           // Render the result as a String of hexadecimal digits
  615           StringBuffer result = new StringBuffer();
  616           for (int i = 0; i < bytes.length; i++) {
  617               byte b1 = (byte) ((bytes[i] & 0xf0) >> 4);
  618               byte b2 = (byte) (bytes[i] & 0x0f);
  619               if (b1 < 10)
  620                   result.append((char) ('0' + b1));
  621               else
  622                   result.append((char) ('A' + (b1 - 10)));
  623               if (b2 < 10)
  624                   result.append((char) ('0' + b2));
  625               else
  626                   result.append((char) ('A' + (b2 - 10)));
  627           }
  628           return (result.toString());
  629   
  630       }
  631   
  632   
  633       /**
  634        * Return the MessageDigest object to be used for calculating
  635        * session identifiers.  If none has been created yet, initialize
  636        * one the first time this method is called.
  637        */
  638       protected synchronized MessageDigest getDigest() {
  639   
  640           if (this.digest == null) {
  641               try {
  642                   this.digest = MessageDigest.getInstance(algorithm);
  643               } catch (NoSuchAlgorithmException e) {
  644                   try {
  645                       this.digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
  646                   } catch (NoSuchAlgorithmException f) {
  647                       this.digest = null;
  648                   }
  649               }
  650           }
  651   
  652           return (this.digest);
  653   
  654       }
  655   
  656   
  657       /**
  658        * Return the random number generator instance we should use for
  659        * generating session identifiers.  If there is no such generator
  660        * currently defined, construct and seed a new one.
  661        */
  662       protected synchronized Random getRandom() {
  663   
  664           if (this.random == null) {
  665               try {
  666                   Class clazz = Class.forName(randomClass);
  667                   this.random = (Random) clazz.newInstance();
  668                   long seed = System.currentTimeMillis();
  669                   char entropy[] = getEntropy().toCharArray();
  670                   for (int i = 0; i < entropy.length; i++) {
  671                       long update = ((byte) entropy[i]) << ((i % 8) * 8);
  672                       seed ^= update;
  673                   }
  674                   this.random.setSeed(seed);
  675               } catch (Exception e) {
  676                   this.random = new java.util.Random();
  677               }
  678           }
  679   
  680           return (this.random);
  681   
  682       }
  683   
  684   
  685       /**
  686        * Attempts reauthentication to the <code>Realm</code> using
  687        * the credentials included in argument <code>entry</code>.
  688        *
  689        * @param ssoId identifier of SingleSignOn session with which the
  690        *              caller is associated
  691        * @param request   the request that needs to be authenticated
  692        */
  693       protected boolean reauthenticateFromSSO(String ssoId, Request request) {
  694   
  695           if (sso == null || ssoId == null)
  696               return false;
  697   
  698           boolean reauthenticated = false;
  699   
  700           Container parent = getContainer();
  701           if (parent != null) {
  702               Realm realm = parent.getRealm();
  703               if (realm != null) {
  704                   reauthenticated = sso.reauthenticate(ssoId, realm, request);
  705               }
  706           }
  707   
  708           if (reauthenticated) {
  709               associate(ssoId, request.getSessionInternal(true));
  710   
  711               if (log.isDebugEnabled()) {
  712                   log.debug(" Reauthenticated cached principal '" +
  713                             request.getUserPrincipal().getName() +
  714                             "' with auth type '" +  request.getAuthType() + "'");
  715               }
  716           }
  717   
  718           return reauthenticated;
  719       }
  720   
  721   
  722       /**
  723        * Register an authenticated Principal and authentication type in our
  724        * request, in the current session (if there is one), and with our
  725        * SingleSignOn valve, if there is one.  Set the appropriate cookie
  726        * to be returned.
  727        *
  728        * @param request The servlet request we are processing
  729        * @param response The servlet response we are generating
  730        * @param principal The authenticated Principal to be registered
  731        * @param authType The authentication type to be registered
  732        * @param username Username used to authenticate (if any)
  733        * @param password Password used to authenticate (if any)
  734        */
  735       protected void register(Request request, Response response,
  736                               Principal principal, String authType,
  737                               String username, String password) {
  738   
  739           if (log.isDebugEnabled())
  740               log.debug("Authenticated '" + principal.getName() + "' with type '"
  741                   + authType + "'");
  742   
  743           // Cache the authentication information in our request
  744           request.setAuthType(authType);
  745           request.setUserPrincipal(principal);
  746   
  747           Session session = request.getSessionInternal(false);
  748           
  749           if (session != null && changeSessionIdOnAuthentication) {
  750               Manager manager = request.getContext().getManager();
  751               manager.changeSessionId(session);
  752               request.changeSessionId(session.getId());
  753           }
  754   
  755           // Cache the authentication information in our session, if any
  756           if (cache) {
  757               if (session != null) {
  758                   session.setAuthType(authType);
  759                   session.setPrincipal(principal);
  760                   if (username != null)
  761                       session.setNote(Constants.SESS_USERNAME_NOTE, username);
  762                   else
  763                       session.removeNote(Constants.SESS_USERNAME_NOTE);
  764                   if (password != null)
  765                       session.setNote(Constants.SESS_PASSWORD_NOTE, password);
  766                   else
  767                       session.removeNote(Constants.SESS_PASSWORD_NOTE);
  768               }
  769           }
  770   
  771           // Construct a cookie to be returned to the client
  772           if (sso == null)
  773               return;
  774   
  775           // Only create a new SSO entry if the SSO did not already set a note
  776           // for an existing entry (as it would do with subsequent requests
  777           // for DIGEST and SSL authenticated contexts)
  778           String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
  779           if (ssoId == null) {
  780               // Construct a cookie to be returned to the client
  781               ssoId = generateSessionId();
  782               Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId);
  783               cookie.setMaxAge(-1);
  784               cookie.setPath("/");
  785               
  786               // Bugzilla 41217
  787               cookie.setSecure(request.isSecure());
  788   
  789               // Bugzilla 34724
  790               String ssoDomain = sso.getCookieDomain();
  791               if(ssoDomain != null) {
  792                   cookie.setDomain(ssoDomain);
  793               }
  794   
  795               response.addCookie(cookie);
  796   
  797               // Register this principal with our SSO valve
  798               sso.register(ssoId, principal, authType, username, password);
  799               request.setNote(Constants.REQ_SSOID_NOTE, ssoId);
  800   
  801           } else {
  802               // Update the SSO session with the latest authentication data
  803               sso.update(ssoId, principal, authType, username, password);
  804           }
  805   
  806           // Fix for Bug 10040
  807           // Always associate a session with a new SSO reqistration.
  808           // SSO entries are only removed from the SSO registry map when
  809           // associated sessions are destroyed; if a new SSO entry is created
  810           // above for this request and the user never revisits the context, the
  811           // SSO entry will never be cleared if we don't associate the session
  812           if (session == null)
  813               session = request.getSessionInternal(true);
  814           sso.associate(ssoId, session);
  815   
  816       }
  817   
  818   
  819       // ------------------------------------------------------ Lifecycle Methods
  820   
  821   
  822       /**
  823        * Add a lifecycle event listener to this component.
  824        *
  825        * @param listener The listener to add
  826        */
  827       public void addLifecycleListener(LifecycleListener listener) {
  828   
  829           lifecycle.addLifecycleListener(listener);
  830   
  831       }
  832   
  833   
  834       /**
  835        * Get the lifecycle listeners associated with this lifecycle. If this 
  836        * Lifecycle has no listeners registered, a zero-length array is returned.
  837        */
  838       public LifecycleListener[] findLifecycleListeners() {
  839   
  840           return lifecycle.findLifecycleListeners();
  841   
  842       }
  843   
  844   
  845       /**
  846        * Remove a lifecycle event listener from this component.
  847        *
  848        * @param listener The listener to remove
  849        */
  850       public void removeLifecycleListener(LifecycleListener listener) {
  851   
  852           lifecycle.removeLifecycleListener(listener);
  853   
  854       }
  855   
  856   
  857       /**
  858        * Prepare for the beginning of active use of the public methods of this
  859        * component.  This method should be called after <code>configure()</code>,
  860        * and before any of the public methods of the component are utilized.
  861        *
  862        * @exception LifecycleException if this component detects a fatal error
  863        *  that prevents this component from being used
  864        */
  865       public void start() throws LifecycleException {
  866   
  867           // Validate and update our current component state
  868           if (started)
  869               throw new LifecycleException
  870                   (sm.getString("authenticator.alreadyStarted"));
  871           lifecycle.fireLifecycleEvent(START_EVENT, null);
  872           started = true;
  873   
  874           // Look up the SingleSignOn implementation in our request processing
  875           // path, if there is one
  876           Container parent = context.getParent();
  877           while ((sso == null) && (parent != null)) {
  878               if (!(parent instanceof Pipeline)) {
  879                   parent = parent.getParent();
  880                   continue;
  881               }
  882               Valve valves[] = ((Pipeline) parent).getValves();
  883               for (int i = 0; i < valves.length; i++) {
  884                   if (valves[i] instanceof SingleSignOn) {
  885                       sso = (SingleSignOn) valves[i];
  886                       break;
  887                   }
  888               }
  889               if (sso == null)
  890                   parent = parent.getParent();
  891           }
  892           if (log.isDebugEnabled()) {
  893               if (sso != null)
  894                   log.debug("Found SingleSignOn Valve at " + sso);
  895               else
  896                   log.debug("No SingleSignOn Valve is present");
  897           }
  898   
  899       }
  900   
  901   
  902       /**
  903        * Gracefully terminate the active use of the public methods of this
  904        * component.  This method should be the last one called on a given
  905        * instance of this component.
  906        *
  907        * @exception LifecycleException if this component detects a fatal error
  908        *  that needs to be reported
  909        */
  910       public void stop() throws LifecycleException {
  911   
  912           // Validate and update our current component state
  913           if (!started)
  914               throw new LifecycleException
  915                   (sm.getString("authenticator.notStarted"));
  916           lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  917           started = false;
  918   
  919           sso = null;
  920   
  921       }
  922   
  923   
  924   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » authenticator » [javadoc | source]