首先要理解两个概念:Subject和Realm,分别是主体及验证主体的数据源。web
身份验证步骤以下:数据库
一、收集用户身份/凭证,即如用户名/密码。apache
(1)web项目配置web.xml,再经过如下语句便可得到用户身份/凭证。spa
Subject subject = SecurityUtils.getSubject();
(2)非web项目则获取用户身份/凭证以下:code
//一、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //二、获得SecurityManager实例 并绑定给SecurityUtils org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //三、获得Subject及建立用户名/密码身份验证Token(即用户身份/凭证) Subject subject = SecurityUtils.getSubject();
二、调用Subject.login进行登陆,若是失败将获得相应的AuthenticationException异常,根据异常提示用户错误信息;不然登陆成功。xml
(1)调用Subject.login(token)进行登陆,这里的token是须要与数据源进行验证的身份及凭证,调用的login方法是Subject接口的实现类DelegatingSubject里的方法,这个方法又委托给接口SecurityManage, SecurityManage经过实现类DefaultSecurityManager的login方法实现。到这里,咱们知道这个login方法实际执行的是DefaultSecurityManager的login方法。继承
(2)须要验证的数据取到了,那么问题来了,如今怎么与数据库里或.Ini文件里的正确身份/凭证进行验证呢。token
DefaultSecurityManager类的login方法调用了authenticate方法,这个方法来源有点复杂。首先、DefaultSecurityManager经过层层继承,最后继承了抽象类AuthenticatingSecurityManager。如图:接口
AuthenticatingSecurityManager实现了Authenticator,Authenticator有个实现类叫作AbstractAuthenticator,以下图。图片
因此咱们AuthenticatingSecurityManager调用的authenticate方法实现实际来源于AbstractAuthenticator,如图:
AbstractAuthenticator继续调用ModularRealmAuthenticator里的方法doAuthenticate,可进行多Realm身份验证,如图,
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); } }
最后doMultiRealmAuthentication调用了咱们以前实现的Realm里的getAuthenticationInfo方法,Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,若是没有返回/抛出异常表示身份验证失败了。此处能够配置多个Realm,将按照相应的顺序及策略进行访问
三、最后调用Subject.logout进行退出操做。