1. subject.login(token);

  2. 接着调用DelegatingSubject的login(AuthenticationToken token)

    1. 在该方法中调用   Subject subject = securityManager.login(this, token);

  3. 接着调用DefaultSecurityManager的 

  public Subject login(Subject subject, AuthenticationToken token)
        throws AuthenticationException
    {
        AuthenticationInfo info;
        try
        {
            info = authenticate(token);
        }


4.其实是调用AuthenticatingSecurityManager的 

public AuthenticationInfo authenticate(AuthenticationToken token)
        throws AuthenticationException
    {
        return authenticator.authenticate(token);
    }


5.authenticator默认为authenticator = new ModularRealmAuthenticator();


6.调用ModularRealmAuthenticator父类AbstractAuthenticator的

public final AuthenticationInfo authenticate(AuthenticationToken token)
        throws AuthenticationException
    {
        if(token == null)
            throw new IllegalArgumentException("Method argumet (authentication token) cannot be null.");
        log.trace("Authentication attempt received for token [{}]", token);
        AuthenticationInfo info;
        try
        {
            info = doAuthenticate(token);


7.方法如下:

  protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)
        throws AuthenticationException
    {
        assertRealmsConfigured();
        Collection realms = getRealms();
        if(realms.size() == 1)
            return doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken);
        else
            return doMultiRealmAuthentication(realms, authenticationToken);
    }

8.doSingleRealmAuthentication的详细过程如下:

  protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token)
    {
        if(!realm.supports(token))
        {
            String msg = (new StringBuilder()).append("Realm [").append(realm).append("] does not support authentication token [").append(token).append("].  Please ensure that the appropriate Realm implementation is ").append("configured correctly or that the realm accepts AuthenticationTokens of this type.").toString();
            throw new UnsupportedTokenException(msg);
        }
        AuthenticationInfo info = realm.getAuthenticationInfo(token);
        if(info == null)
        {
            String msg = (new StringBuilder()).append("Realm [").append(realm).append("] was unable to find account data for the ").append("submitted AuthenticationToken [").append(token).append("].").toString();
            throw new UnknownAccountException(msg);
        } else
        {
            return info;
        }
    }

9.接着调用realm的getAuthenticationInfo(token)方法

该方法为父类public abstract class AuthenticatingRealm extends CachingRealm

中的方法

  public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
        throws AuthenticationException
    {
        AuthenticationInfo info = getCachedAuthenticationInfo(token);
        if(info == null)
        {
            info = doGetAuthenticationInfo(token);//根据用户名获取相关的用户信息
            log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
            if(token != null && info != null)
                cacheAuthenticationInfoIfPossible(token, info);
        } else
        {
            log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
        }
        if(info != null)
            assertCredentialsMatch(token, info);//具体的验证过程
        else
            log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}].  Returning null.", token);
        return info;
    }

10.

doGetAuthenticationInfo

可以在具体子类中实现:

public class SimpleAccountRealm extends AuthorizingRealm {
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
        throws AuthenticationException
    {
        UsernamePasswordToken upToken = (UsernamePasswordToken)token;
        SimpleAccount account = getUser(upToken.getUsername());
        if(account != null)
        {
            if(account.isLocked())
                throw new LockedAccountException((new StringBuilder()).append("Account [").append(account).append("] is locked.").toString());
            if(account.isCredentialsExpired())
            {
                String msg = (new StringBuilder()).append("The credentials for account [").append(account).append("] are expired").toString();
                throw new ExpiredCredentialsException(msg);
            }
        }
        return account;
    }