org.apache.catalina.authenticator

## Class AuthenticatorBase

- java.lang.Object
- - org.apache.catalina.util.LifecycleBase
  - - org.apache.catalina.util.LifecycleMBeanBase
    - - org.apache.catalina.valves.ValveBase
      - - org.apache.catalina.authenticator.AuthenticatorBase

- All Implemented Interfaces:
    MBeanRegistration, RegistrationListener, Authenticator, Contained, JmxEnabled, Lifecycle, Valve
  Direct Known Subclasses:
    BasicAuthenticator, DigestAuthenticator, FormAuthenticator, NonLoginAuthenticator, SpnegoAuthenticator, SSLAuthenticator

      public abstract class AuthenticatorBase
      extends ValveBase
      implements Authenticator, RegistrationListener

  Basic implementation of the Valve interface that enforces the `<security-constraint>` elements in the web application deployment descriptor. This functionality is implemented as a Valve so that it can be omitted in environments that do not require these features. Individual implementations of each supported authentication method can subclass this base class as required.

  USAGE CONSTRAINT: When this class is utilized, the Context to which it is attached (or a parent Container in a hierarchy) must have an associated Realm that can be used for authenticating users and enumerating the roles to which they have been assigned.

  USAGE CONSTRAINT: This Valve is only useful when processing HTTP requests. Requests of any other type will simply be passed through.

  Author:
    Craig R. McClanahan

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `protected static class` | `AuthenticatorBase.AllowCorsPreflight`

    - ### Nested classes/interfaces inherited from interface org.apache.catalina.Lifecycle

      `Lifecycle.SingleUse`

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected boolean` | `alwaysUseSession` Should a session always be used once a user is authenticated?
    `protected static String` | `AUTH_HEADER_NAME` Authentication header
    `protected boolean` | `cache` Should we cache authenticated Principals if the request is part of an HTTP session?
    `protected boolean` | `changeSessionIdOnAuthentication` Should the session ID, if any, be changed upon a successful authentication to prevent a session fixation attack?
    `protected Context` | `context` The Context to which this Valve is attached.
    `protected boolean` | `disableProxyCaching` Flag to determine if we disable proxy caching, or leave the issue up to the webapp developer.
    `protected String` | `jaspicCallbackHandlerClass` The name of the JASPIC callback handler class.
    `protected static String` | `REALM_NAME` Default authentication realm name.
    `protected boolean` | `securePagesWithPragma` Flag to determine if we disable proxy caching with headers incompatible with IE.
    `protected String` | `secureRandomAlgorithm` The name of the algorithm to use to create instances of `SecureRandom` which are used to generate SSO session IDs.
    `protected String` | `secureRandomClass` The Java class name of the secure random number generator class to be used when generating SSO session identifiers.
    `protected String` | `secureRandomProvider` The name of the provider to use to create instances of `SecureRandom` which are used to generate session SSO IDs.
    `protected boolean` | `sendAuthInfoResponseHeaders` Should the auth information (remote user and auth type) be returned as response headers for a forwarded/proxied request?
    `protected SessionIdGeneratorBase` | `sessionIdGenerator`
    `protected static StringManager` | `sm` The string manager for this package.
    `protected SingleSignOn` | `sso` The SingleSignOn implementation in our request processing chain, if there is one.

    - ### Fields inherited from class org.apache.catalina.valves.ValveBase

      `asyncSupported, container, containerLog, next`

    - ### Fields inherited from class org.apache.catalina.util.LifecycleMBeanBase

      `mserver`

    - ### Fields inherited from interface org.apache.catalina.Lifecycle

      `AFTER_DESTROY_EVENT, AFTER_INIT_EVENT, AFTER_START_EVENT, AFTER_STOP_EVENT, BEFORE_DESTROY_EVENT, BEFORE_INIT_EVENT, BEFORE_START_EVENT, BEFORE_STOP_EVENT, CONFIGURE_START_EVENT, CONFIGURE_STOP_EVENT, PERIODIC_EVENT, START_EVENT, STOP_EVENT`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `AuthenticatorBase()`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected boolean` | `allowCorsPreflightBypass(Request request)`
    `protected void` | `associate(String ssoId, Session session)` Associate the specified single sign on identifier with the specified Session.
    `boolean` | `authenticate(Request request, HttpServletResponse httpResponse)` Authenticate the user making this request, based on the login configuration of the `Context` with which this Authenticator is associated.
    `protected String` | `changeSessionID(Request request, Session session)`
    `protected boolean` | `checkForCachedAuthentication(Request request, HttpServletResponse response, boolean useSSO)` Check to see if the user has already been authenticated earlier in the processing chain or if there is enough information available to authenticate the user without requiring further user interaction.
    `protected abstract boolean` | `doAuthenticate(Request request, HttpServletResponse response)` Provided for sub-classes to implement their specific authentication mechanism.
    `protected Principal` | `doLogin(Request request, String username, String password)` Process the login request.
    `String` | `getAllowCorsPreflight()`
    `boolean` | `getAlwaysUseSession()`
    `protected abstract String` | `getAuthMethod()`
    `boolean` | `getCache()` Return the cache authenticated Principals flag.
    `boolean` | `getChangeSessionIdOnAuthentication()` Return the flag that states if we should change the session ID of an existing session upon successful authentication.
    `Container` | `getContainer()` Return the Container to which this Valve is attached.
    `boolean` | `getDisableProxyCaching()` Return the flag that states if we add headers to disable caching by proxies.
    `String` | `getJaspicCallbackHandlerClass()` Return the JASPIC callback handler class name
    `protected static String` | `getRealmName(Context context)`
    `protected X509Certificate[]` | `getRequestCertificates(Request request)` Look for the X509 certificate chain in the Request under the key `javax.servlet.request.X509Certificate`.
    `boolean` | `getSecurePagesWithPragma()` Return the flag that states, if proxy caching is disabled, what headers we add to disable the caching.
    `String` | `getSecureRandomAlgorithm()` Return the secure random number generator algorithm name.
    `String` | `getSecureRandomClass()` Return the secure random number generator class name.
    `String` | `getSecureRandomProvider()` Return the secure random number generator provider name.
    `void` | `invoke(Request request, Response response)` Enforce the security restrictions in the web application deployment descriptor of our associated Context.
    `protected boolean` | `isContinuationRequired(Request request)` Does this authenticator require that `authenticate(Request, HttpServletResponse)` is called to continue an authentication process that started in a previous request?
    `boolean` | `isSendAuthInfoResponseHeaders()` Returns the flag whether authentication information will be sent to a reverse proxy on a forwarded request.
    `void` | `login(String username, String password, Request request)`
    `void` | `logout(Request request)`
    `void` | `notify(String layer, String appContext)`
    `protected boolean` | `reauthenticateFromSSO(String ssoId, Request request)` Attempts reauthentication to the `Realm` using the credentials included in argument `entry`.
    `void` | `register(Request request, HttpServletResponse response, Principal principal, String authType, String username, String password)` Register an authenticated Principal and authentication type in our request, in the current session (if there is one), and with our SingleSignOn valve, if there is one.
    `protected void` | `register(Request request, HttpServletResponse response, Principal principal, String authType, String username, String password, boolean alwaysUseSession, boolean cache)` Register an authenticated Principal and authentication type in our request, in the current session (if there is one), and with our SingleSignOn valve, if there is one.
    `void` | `setAllowCorsPreflight(String allowCorsPreflight)`
    `void` | `setAlwaysUseSession(boolean alwaysUseSession)`
    `void` | `setCache(boolean cache)` Set the cache authenticated Principals flag.
    `void` | `setChangeSessionIdOnAuthentication(boolean changeSessionIdOnAuthentication)` Set the value of the flag that states if we should change the session ID of an existing session upon successful authentication.
    `void` | `setContainer(Container container)` Set the Container to which this Valve is attached.
    `void` | `setDisableProxyCaching(boolean nocache)` Set the value of the flag that states if we add headers to disable caching by proxies.
    `void` | `setJaspicCallbackHandlerClass(String jaspicCallbackHandlerClass)` Set the JASPIC callback handler class name
    `void` | `setSecurePagesWithPragma(boolean securePagesWithPragma)` Set the value of the flag that states what headers we add to disable proxy caching.
    `void` | `setSecureRandomAlgorithm(String secureRandomAlgorithm)` Set the secure random number generator algorithm name.
    `void` | `setSecureRandomClass(String secureRandomClass)` Set the secure random number generator class name.
    `void` | `setSecureRandomProvider(String secureRandomProvider)` Set the secure random number generator provider name.
    `void` | `setSendAuthInfoResponseHeaders(boolean sendAuthInfoResponseHeaders)` Sets the flag whether authentication information will be send to a reverse proxy on a forwarded request.
    `protected void` | `startInternal()` Start this component and implement the requirements of `LifecycleBase.startInternal()`.
    `protected void` | `stopInternal()` Stop this component and implement the requirements of `LifecycleBase.stopInternal()`.

    - ### Methods inherited from class org.apache.catalina.valves.ValveBase

      `backgroundProcess, getDomainInternal, getNext, getObjectNameKeyProperties, initInternal, isAsyncSupported, setAsyncSupported, setNext, toString`

    - ### Methods inherited from class org.apache.catalina.util.LifecycleMBeanBase

      `destroyInternal, getDomain, getObjectName, postDeregister, postRegister, preDeregister, preRegister, register, setDomain, unregister`

    - ### Methods inherited from class org.apache.catalina.util.LifecycleBase

      `addLifecycleListener, destroy, findLifecycleListeners, fireLifecycleEvent, getState, getStateName, getThrowOnFailure, init, removeLifecycleListener, setState, setState, setThrowOnFailure, start, stop`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### sm

          protected static final StringManager sm

      The string manager for this package.

    - #### AUTH_HEADER_NAME

          protected static final String AUTH_HEADER_NAME

      Authentication header
      See Also:
        Constant Field Values

    - #### REALM_NAME

          protected static final String REALM_NAME

      Default authentication realm name.
      See Also:
        Constant Field Values

    - #### alwaysUseSession

          protected boolean alwaysUseSession

      Should a session always be used once a user is authenticated? This may offer some performance benefits since the session can then be used to cache the authenticated Principal, hence removing the need to authenticate the user via the Realm on every request. This may be of help for combinations such as BASIC authentication used with the JNDIRealm or DataSourceRealms. However there will also be the performance cost of creating and GC'ing the session. By default, a session will not be created.

    - #### cache

          protected boolean cache

      Should we cache authenticated Principals if the request is part of an HTTP session?

    - #### changeSessionIdOnAuthentication

          protected boolean changeSessionIdOnAuthentication

      Should the session ID, if any, be changed upon a successful authentication to prevent a session fixation attack?

    - #### context

          protected Context context

      The Context to which this Valve is attached.

    - #### disableProxyCaching

          protected boolean disableProxyCaching

      Flag to determine if we disable proxy caching, or leave the issue up to the webapp developer.

    - #### securePagesWithPragma

          protected boolean securePagesWithPragma

      Flag to determine if we disable proxy caching with headers incompatible with IE.

    - #### secureRandomClass

          protected String secureRandomClass

      The Java class name of the secure random number generator class to be used when generating SSO session identifiers. The random number generator class must be self-seeding and have a zero-argument constructor. If not specified, an instance of `SecureRandom` will be generated.

    - #### secureRandomAlgorithm

          protected String secureRandomAlgorithm

      The name of the algorithm to use to create instances of `SecureRandom` which are used to generate SSO session IDs. If no algorithm is specified, SHA1PRNG is used. To use the platform default (which may be SHA1PRNG), specify the empty string. If an invalid algorithm and/or provider is specified the SecureRandom instances will be created using the defaults. If that fails, the SecureRandom instances will be created using platform defaults.

    - #### secureRandomProvider

          protected String secureRandomProvider

      The name of the provider to use to create instances of `SecureRandom` which are used to generate session SSO IDs. If no algorithm is specified the of SHA1PRNG default is used. If an invalid algorithm and/or provider is specified the SecureRandom instances will be created using the defaults. If that fails, the SecureRandom instances will be created using platform defaults.

    - #### jaspicCallbackHandlerClass

          protected String jaspicCallbackHandlerClass

      The name of the JASPIC callback handler class. If none is specified the default `CallbackHandlerImpl` will be used.

    - #### sendAuthInfoResponseHeaders

          protected boolean sendAuthInfoResponseHeaders

      Should the auth information (remote user and auth type) be returned as response headers for a forwarded/proxied request? When the `RemoteIpValve` or `RemoteIpFilter` mark a forwarded request with the `Globals.REQUEST_FORWARDED_ATTRIBUTE` this authenticator can return the values of `HttpServletRequest.getRemoteUser()` and `HttpServletRequest.getAuthType()` as response headers `remote-user` and `auth-type` to a reverse proxy. This is useful, e.g., for access log consistency or other decisions to make.

    - #### sessionIdGenerator

          protected SessionIdGeneratorBase sessionIdGenerator

    - #### sso

          protected SingleSignOn sso

      The SingleSignOn implementation in our request processing chain, if there is one.

  - ### Constructor Detail

    - #### AuthenticatorBase

          public AuthenticatorBase()

  - ### Method Detail

    - #### getRealmName

          protected static String getRealmName(Context context)

    - #### getAllowCorsPreflight

          public String getAllowCorsPreflight()

    - #### setAllowCorsPreflight

          public void setAllowCorsPreflight(String allowCorsPreflight)

    - #### getAlwaysUseSession

          public boolean getAlwaysUseSession()

    - #### setAlwaysUseSession

          public void setAlwaysUseSession(boolean alwaysUseSession)

    - #### getCache

          public boolean getCache()

      Return the cache authenticated Principals flag.
      Returns:
        `true` if authenticated Principals will be cached, otherwise `false`

    - #### setCache

          public void setCache(boolean cache)

      Set the cache authenticated Principals flag.
      Parameters:
        `cache` - The new cache flag

    - #### getContainer

          public Container getContainer()

      Return the Container to which this Valve is attached.
      Specified by:
        `getContainer` in interface `Contained`
      Overrides:
        `getContainer` in class `ValveBase`
      Returns:
        The Container with which this instance is associated or `null` if not associated with a Container

    - #### setContainer

          public void setContainer(Container container)

      Set the Container to which this Valve is attached.
      Specified by:
        `setContainer` in interface `Contained`
      Overrides:
        `setContainer` in class `ValveBase`
      Parameters:
        `container` - The container to which we are attached

    - #### getDisableProxyCaching

          public boolean getDisableProxyCaching()

      Return the flag that states if we add headers to disable caching by proxies.
      Returns:
        `true` if the headers will be added, otherwise `false`

    - #### setDisableProxyCaching

          public void setDisableProxyCaching(boolean nocache)

      Set the value of the flag that states if we add headers to disable caching by proxies.
      Parameters:
        `nocache` - `true` if we add headers to disable proxy caching, `false` if we leave the headers alone.

    - #### getSecurePagesWithPragma

          public boolean getSecurePagesWithPragma()

      Return the flag that states, if proxy caching is disabled, what headers we add to disable the caching.
      Returns:
        `true` if a Pragma header should be used, otherwise `false`

    - #### setSecurePagesWithPragma

          public void setSecurePagesWithPragma(boolean securePagesWithPragma)

      Set the value of the flag that states what headers we add to disable proxy caching.
      Parameters:
        `securePagesWithPragma` - `true` if we add headers which are incompatible with downloading office documents in IE under SSL but which fix a caching problem in Mozilla.

    - #### getChangeSessionIdOnAuthentication

          public boolean getChangeSessionIdOnAuthentication()

      Return the flag that states if we should change the session ID of an existing session upon successful authentication.
      Returns:
        `true` to change session ID upon successful authentication, `false` to do not perform the change.

    - #### setChangeSessionIdOnAuthentication

          public void setChangeSessionIdOnAuthentication(boolean changeSessionIdOnAuthentication)

      Set the value of the flag that states if we should change the session ID of an existing session upon successful authentication.
      Parameters:
        `changeSessionIdOnAuthentication` - `true` to change session ID upon successful authentication, `false` to do not perform the change.

    - #### getSecureRandomClass

          public String getSecureRandomClass()

      Return the secure random number generator class name.
      Returns:
        The fully qualified name of the SecureRandom implementation to use

    - #### setSecureRandomClass

          public void setSecureRandomClass(String secureRandomClass)

      Set the secure random number generator class name.
      Parameters:
        `secureRandomClass` - The new secure random number generator class name

    - #### getSecureRandomAlgorithm

          public String getSecureRandomAlgorithm()

      Return the secure random number generator algorithm name.
      Returns:
        The name of the SecureRandom algorithm used

    - #### setSecureRandomAlgorithm

          public void setSecureRandomAlgorithm(String secureRandomAlgorithm)

      Set the secure random number generator algorithm name.
      Parameters:
        `secureRandomAlgorithm` - The new secure random number generator algorithm name

    - #### getSecureRandomProvider

          public String getSecureRandomProvider()

      Return the secure random number generator provider name.
      Returns:
        The name of the SecureRandom provider

    - #### setSecureRandomProvider

          public void setSecureRandomProvider(String secureRandomProvider)

      Set the secure random number generator provider name.
      Parameters:
        `secureRandomProvider` - The new secure random number generator provider name

    - #### getJaspicCallbackHandlerClass

          public String getJaspicCallbackHandlerClass()

      Return the JASPIC callback handler class name
      Returns:
        The name of the JASPIC callback handler

    - #### setJaspicCallbackHandlerClass

          public void setJaspicCallbackHandlerClass(String jaspicCallbackHandlerClass)

      Set the JASPIC callback handler class name
      Parameters:
        `jaspicCallbackHandlerClass` - The new JASPIC callback handler class name

    - #### isSendAuthInfoResponseHeaders

          public boolean isSendAuthInfoResponseHeaders()

      Returns the flag whether authentication information will be sent to a reverse proxy on a forwarded request.
      Returns:
        `true` if response headers shall be sent, `false` otherwise

    - #### setSendAuthInfoResponseHeaders

          public void setSendAuthInfoResponseHeaders(boolean sendAuthInfoResponseHeaders)

      Sets the flag whether authentication information will be send to a reverse proxy on a forwarded request.
      Parameters:
        `sendAuthInfoResponseHeaders` - `true` if response headers shall be sent, `false` otherwise

    - #### invoke

          public void invoke(Request request,
                    Response response)
                      throws IOException,
                             ServletException

      Enforce the security restrictions in the web application deployment descriptor of our associated Context.
      Specified by:
        `invoke` in interface `Valve`
      Parameters:
        `request` - Request to be processed
        `response` - Response to be processed
      Throws:
        `IOException` - if an input/output error occurs
        `ServletException` - if thrown by a processing element

    - #### allowCorsPreflightBypass

          protected boolean allowCorsPreflightBypass(Request request)

    - #### authenticate

          public boolean authenticate(Request request,
                             HttpServletResponse httpResponse)
                               throws IOException

      Description copied from interface: `Authenticator`
      Authenticate the user making this request, based on the login configuration of the `Context` with which this Authenticator is associated.
      Specified by:
        `authenticate` in interface `Authenticator`
      Parameters:
        `request` - Request we are processing
        `httpResponse` - Response we are populating
      Returns:
        `true` if any specified constraints have been satisfied, or `false` if one more constraints were not satisfied (in which case an authentication challenge will have been written to the response).
      Throws:
        `IOException` - if an input/output error occurs

    - #### doAuthenticate

          protected abstract boolean doAuthenticate(Request request,
                               HttpServletResponse response)
                                             throws IOException

      Provided for sub-classes to implement their specific authentication mechanism.
      Parameters:
        `request` - The request that triggered the authentication
        `response` - The response associated with the request
      Returns:
        `true` if the the user was authenticated, otherwise `false`, in which case an authentication challenge will have been written to the response
      Throws:
        `IOException` - If an I/O problem occurred during the authentication process

    - #### isContinuationRequired

          protected boolean isContinuationRequired(Request request)

      Does this authenticator require that `authenticate(Request, HttpServletResponse)` is called to continue an authentication process that started in a previous request?
      Parameters:
        `request` - The request currently being processed
      Returns:
        `true` if authenticate() must be called, otherwise `false`

    - #### getRequestCertificates

          protected X509Certificate[] getRequestCertificates(Request request)
                                                      throws IllegalStateException

      Look for the X509 certificate chain in the Request under the key `javax.servlet.request.X509Certificate`. If not found, trigger extracting the certificate chain from the Coyote request.
      Parameters:
        `request` - Request to be processed
      Returns:
        The X509 certificate chain if found, `null` otherwise.
      Throws:
        `IllegalStateException`

    - #### associate

          protected void associate(String ssoId,
                       Session session)

      Associate the specified single sign on identifier with the specified Session.
      Parameters:
        `ssoId` - Single sign on identifier
        `session` - Session to be associated

    - #### checkForCachedAuthentication

          protected boolean checkForCachedAuthentication(Request request,
                                             HttpServletResponse response,
                                             boolean useSSO)

      Check to see if the user has already been authenticated earlier in the processing chain or if there is enough information available to authenticate the user without requiring further user interaction.
      Parameters:
        `request` - The current request
        `response` - The current response
        `useSSO` - Should information available from SSO be used to attempt to authenticate the current user?
      Returns:
        `true` if the user was authenticated via the cache, otherwise `false`

    - #### reauthenticateFromSSO

          protected boolean reauthenticateFromSSO(String ssoId,
                                      Request request)

      Attempts reauthentication to the `Realm` using the credentials included in argument `entry`.
      Parameters:
        `ssoId` - identifier of SingleSignOn session with which the caller is associated
        `request` - the request that needs to be authenticated
      Returns:
        `true` if the reauthentication from SSL occurred

    - #### register

          public void register(Request request,
                      HttpServletResponse response,
                      Principal principal,
                      String authType,
                      String username,
                      String password)

      Register an authenticated Principal and authentication type in our request, in the current session (if there is one), and with our SingleSignOn valve, if there is one. Set the appropriate cookie to be returned.
      Parameters:
        `request` - The servlet request we are processing
        `response` - The servlet response we are generating
        `principal` - The authenticated Principal to be registered
        `authType` - The authentication type to be registered
        `username` - Username used to authenticate (if any)
        `password` - Password used to authenticate (if any)

    - #### register

          protected void register(Request request,
                      HttpServletResponse response,
                      Principal principal,
                      String authType,
                      String username,
                      String password,
                      boolean alwaysUseSession,
                      boolean cache)

      Register an authenticated Principal and authentication type in our request, in the current session (if there is one), and with our SingleSignOn valve, if there is one. Set the appropriate cookie to be returned.
      Parameters:
        `request` - The servlet request we are processing
        `response` - The servlet response we are generating
        `principal` - The authenticated Principal to be registered
        `authType` - The authentication type to be registered
        `username` - Username used to authenticate (if any)
        `password` - Password used to authenticate (if any)
        `alwaysUseSession` - Should a session always be used once a user is authenticated?
        `cache` - Should we cache authenticated Principals if the request is part of an HTTP session?

    - #### changeSessionID

          protected String changeSessionID(Request request,
                               Session session)

    - #### login

          public void login(String username,
                   String password,
                   Request request)
                     throws ServletException

      Specified by:
        `login` in interface `Authenticator`
      Throws:
        `ServletException`

    - #### getAuthMethod

          protected abstract String getAuthMethod()

    - #### doLogin

          protected Principal doLogin(Request request,
                          String username,
                          String password)
                               throws ServletException

      Process the login request.
      Parameters:
        `request` - Associated request
        `username` - The user
        `password` - The password
      Returns:
        The authenticated Principal
      Throws:
        `ServletException` - No principal was authenticated with the specified credentials

    - #### logout

          public void logout(Request request)

      Specified by:
        `logout` in interface `Authenticator`

    - #### startInternal

          protected void startInternal()
                                throws LifecycleException

      Start this component and implement the requirements of `LifecycleBase.startInternal()`.
      Overrides:
        `startInternal` in class `ValveBase`
      Throws:
        `LifecycleException` - if this component detects a fatal error that prevents this component from being used

    - #### stopInternal

          protected void stopInternal()
                               throws LifecycleException

      Stop this component and implement the requirements of `LifecycleBase.stopInternal()`.
      Overrides:
        `stopInternal` in class `ValveBase`
      Throws:
        `LifecycleException` - if this component detects a fatal error that prevents this component from being used

    - #### notify

          public void notify(String layer,
                    String appContext)

      Specified by:
        `notify` in interface `RegistrationListener`

Copyright © 2000-2021 Apache Software Foundation. All Rights Reserved.