ModularRealmAuthenticator source code analysis and configurationCopy the code

After SecurityManager token information, by calling the authenticator, authenticate (token) method, the authentication entrusted to the built-in examples validate the authenticator. The authenticator is usually ModularRealmAuthenticator instance, support for one or more of the Realm instance adaptation. ModularRealmAuthenticator provides a pluggable authentication style, you can insert custom Realm implementations.

If configured with multiple Realm, ModularRealmAuthenticator depending on the configuration AuthenticationStrategy (authentication strategy) Realm more certification process. Note: If only one Realm is configured in the application, the Realm will be called directly without the need to configure authentication policies.

It determines whether each Realm supports the submitted token, and if it does, the getAuthenticationInfo (token) method is invoked for authentication. The AuthenticationStrategy is covered later

public abstract class AbstractAuthenticator implements Authenticator, LogoutAware { public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException { if (token == null) { throw new IllegalArgumentException("Method argument (authentication token) cannot be null."); } log.trace("Authentication attempt received for token [{}]", token); AuthenticationInfo info; Call ModularRealmAuthenticator try {* / /. DoAuthenticate (token) method * info = doAuthenticate(token); if (info == null) { String msg = "No account information found for authentication token [" + token + "] by this " + "Authenticator instance. Please check that it is configured correctly."; throw new AuthenticationException(msg); } } catch (Throwable t) { AuthenticationException ae = null; if (t instanceof AuthenticationException) { ae = (AuthenticationException) t; } if (ae == null) { //Exception thrown was not an expected AuthenticationException. Therefore it is probably a little more //severe or unexpected. So, wrap in an AuthenticationException, log to warn, and propagate: String msg = "Authentication failed for token submission [" + token + "]. Possible unexpected " + "error? (Typical or expected login exceptions should extend from AuthenticationException)."; ae = new AuthenticationException(msg, t); if (log.isWarnEnabled()) log.warn(msg, t); } try { notifyFailure(token, ae); } catch (Throwable t2) { if (log.isWarnEnabled()) { String msg = "Unable to send notification for failed authentication attempt - listener error? . " + "Please check your AuthenticationListener implementation(s). Logging sending exception " + "and propagating original AuthenticationException instead..." ; log.warn(msg, t2); } } throw ae; } log.debug("Authentication successful for token [{}]. Returned account [{}]", token, info); notifySuccess(token, info); return info; } protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token) throws AuthenticationException; }Copy the code

ModularRealmAuthenticator source code analysis

public class ModularRealmAuthenticator extends AbstractAuthenticator { protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { assertRealmsConfigured(); Collection<Realm> realms = getRealms(); if (realms.size() == 1) { return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken); } else { return doMultiRealmAuthentication(realms, authenticationToken); }}}Copy the code

Realm ==1Copy the code
public class ModularRealmAuthenticator extends AbstractAuthenticator { protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { if (! realm.supports(token)) { String msg = "Realm [" + realm + "] does not support authentication token [" + token + "]. Please ensure that the appropriate Realm implementation is " + "configured correctly or that the realm accepts AuthenticationTokens of this type."; throw new UnsupportedTokenException(msg); } / / to call the custom authentication method in the realm of AuthenticationInfo info = realm. GetAuthenticationInfo (token); if (info == null) { String msg = "Realm [" + realm + "] was unable to find account data for the " + "submitted AuthenticationToken [" + token + "]."; throw new UnknownAccountException(msg); } return info; }}Copy the code

Realms! =1 >AuthenticationStrategy

The authentication result is based on the policy

public class ModularRealmAuthenticator extends AbstractAuthenticator { protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {/ / certified strategy AuthenticationStrategy strategy = getAuthenticationStrategy (); AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token); if (log.isTraceEnabled()) { log.trace("Iterating through {} realms for PAM authentication", realms.size()); } for (Realm realm : realms) { aggregate = strategy.beforeAttempt(realm, token, aggregate); if (realm.supports(token)) { log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm); AuthenticationInfo info = null; Throwable t = null; try { info = realm.getAuthenticationInfo(token); } catch (Throwable throwable) { t = throwable; if (log.isDebugEnabled()) { String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:"; log.debug(msg, t); } } aggregate = strategy.afterAttempt(realm, token, info, aggregate, t); } else { log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token); } } aggregate = strategy.afterAllAttempts(token, aggregate); return aggregate; }}Copy the code

// To invoke authentication methods in the custom realm

AuthenticationInfo info = realm.getAuthenticationInfo(token); A multi-realm is a for loop call to getAuthenticationInfo (token);Copy the code
Public class MyRealm extends AuthorizingRealm {// Public class MyRealm extends AuthenticatingRealm {/** * AuthenticatingRealm ** @param  token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; String username = usernamePasswordToken.getUsername(); String password = String.valueOf(usernamePasswordToken.getPassword()); ByteSource solt = ByteSource.Util.bytes(username); if (username.equals("username") && password.equals("password")) { return new SimpleAuthenticationInfo(username, password, getName()); } return null; }}Copy the code

Do password comparison

 public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {
 
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
    CredentialsMatcher cm = getCredentialsMatcher();
    if (cm != null) {
        if (!cm.doCredentialsMatch(token, info)) {
            //not successful - throw an exception to indicate this:
            String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
            throw new IncorrectCredentialsException(msg);
        }
    } else {
        throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
                "credentials during authentication.  If you do not wish for credentials to be examined, you " +
                "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
    }
}
 
}
Copy the code