Shiro登录验证源码解析

来源:互联网 发布:两岸统一知乎 编辑:程序博客网 时间:2024/06/05 04:38

Shiro登录验证源码解析

登录测试用例

  1. 测试用例

@Testpublic void testShiroLogin() {    //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager    Factory<org.apache.shiro.mgt.SecurityManager> factory =            new IniSecurityManagerFactory("classpath:shiro.ini");    //2、得到SecurityManager实例 并绑定给SecurityUtils    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();    SecurityUtils.setSecurityManager(securityManager);    //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)    Subject subject = SecurityUtils.getSubject();    UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");    try {        //4、登录,即身份验证        subject.login(token);    } catch (AuthenticationException e) {        //5、身份验证失败    }    Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录    //6、退出    subject.logout();}

  1. DelegatingSubject.login(AuthenticationToken token)

public void login(AuthenticationToken token) throws AuthenticationException {    clearRunAsIdentitiesInternal();    Subject subject = securityManager.login(this, token);    PrincipalCollection principals;    String host = null;    if (subject instanceof DelegatingSubject) {        DelegatingSubject delegating = (DelegatingSubject) subject;        //we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:        principals = delegating.principals;        host = delegating.host;    } else {        principals = subject.getPrincipals();    }    if (principals == null || principals.isEmpty()) {        String msg = "Principals returned from securityManager.login( token ) returned a null or " +                "empty value.  This value must be non null and populated with one or more elements.";        throw new IllegalStateException(msg);    }    this.principals = principals;    this.authenticated = true;    if (token instanceof HostAuthenticationToken) {        host = ((HostAuthenticationToken) token).getHost();    }    if (host != null) {        this.host = host;    }    Session session = subject.getSession(false);    if (session != null) {        this.session = decorate(session);    } else {        this.session = null;    }}

  1. DefaultSecurityManager.login(Subject subject, AuthenticationToken token)

public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {    AuthenticationInfo info;    try {        info = authenticate(token);    } catch (AuthenticationException ae) {        try {            onFailedLogin(token, ae, subject);        } catch (Exception e) {            if (log.isInfoEnabled()) {                log.info("onFailedLogin method threw an " +                        "exception.  Logging and propagating original AuthenticationException.", e);            }        }        throw ae; //propagate    }    Subject loggedIn = createSubject(token, info, subject);    onSuccessfulLogin(token, info, loggedIn);    return loggedIn;}

/** * Delegates to the wrapped {@link org.apache.shiro.authc.Authenticator Authenticator} for authentication. */public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {    return this.authenticator.authenticate(token);}

AbstractAuthenticator.authenticate(AuthenticationToken token)

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);        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);        }        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;}

ModularRealmAuthenticator.doAuthenticate(AuthenticationToken authenticationToken)

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);    }}

ModularRealmAuthenticator.assertRealmsConfigured()

protected void assertRealmsConfigured() throws IllegalStateException {    Collection<Realm> realms = getRealms();    if (CollectionUtils.isEmpty(realms)) {        String msg = "Configuration error:  No realms have been configured!  One or more realms must be " +                "present to execute an authentication attempt.";        throw new IllegalStateException(msg);    }} protected Collection<Realm> getRealms() {    return this.realms;}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);    }    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;}

AuthenticatingRealm.getAuthenticationInfo(AuthenticationToken token)

public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {    AuthenticationInfo info = getCachedAuthenticationInfo(token);    if (info == null) {        //otherwise not cached, perform the lookup:        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;}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.");    }}

SimpleCredentialsMatcher.doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)

 public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {    Object tokenCredentials = getCredentials(token);    Object accountCredentials = getCredentials(info);    return equals(tokenCredentials, accountCredentials);}

0 0
原创粉丝点击