shiro身份认证(第一章)
来源:互联网 发布:阿里云日本服务器 编辑:程序博客网 时间:2024/05/17 06:04
shiro版本信息:
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.3.2</version></dependency>当我们调用shiro的subject.login(token)进行登录时,subject的默认实现是:org.apache.shiro.subject.support.DelegatingSubject
Subject subject=SecurityUtils.getSubject();UsernamePasswordToken token=new UsernamePasswordToken("zhang", "123");subject.login(token);
shiro的实现类的源码如下:
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; } }首先判断session是否已经存在,如果已经存在,就清除掉session中原来的信息。
private void clearRunAsIdentities() { Session session = getSession(false); if (session != null) { session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY); } }然后委托给securityManager进行登录。securityManager的默认实现是:org.apache.shiro.mgt.DefaultSecurityManager,源码如下:
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; }securityManager委托给了org.apache.shiro.authc.Authenticator进行处理
public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException { return this.authenticator.authenticate(token); }Authenticator的默认实现是:org.apache.shiro.authc.pam.ModularRealmAuthenticator.ModularRealmAuthenticator
ModularRealmAuthenticator继承了org.apache.shiro.authc.AbstractAuthenticator,并实现了父类定义的抽象方法,AbstractAuthenticator的源码如下:
ModularRealmAuthenticator实现的doAuthenticate方法如下:
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 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); } }首先验证了realm是否存在,然后针对多Realm和一个realm分别提供了不同的实现方法:
针对一个Realm的方法实现,首先判断Realm是否支持验证这种token,然后调用realm的getAuthenticationInfo方法进行验证
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; }Realm的默认实现是org.apache.shiro.realm.AuthenticatingRealm,AuthenticatingRealm实现了getAuthenticationInfo方法:
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; }
doGetAuthenticationInfo是一个抽象方法,先根据token去缓存中取,如果缓存中没有,就交给子类去实现,子类找到了之后把用户信息放到缓存里。
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."); } }assertCredentialsMatch方法用来验证token的密码是否正确,验证不通过则抛出异常。针对多个realm的方法的实现如下:protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) { 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.isWarnEnabled()) { String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:"; log.warn(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; }此处委托给了AuthenticationStrategy依次调用realm进行多realm进行认证。使用AuthenticationStrategy进行认证可以配置不同的策略,例如:一个realm认证通过就可以,或者所有realm都认证通过,以及realm认证的顺序。
完。
阅读全文
0 0
- shiro身份认证(第一章)
- 身份认证(shiro)
- Apache Shiro身份认证(Authentication)
- 2 Apache Shiro 身份认证(登录)
- Shiro框架身份认证(二)
- shiro身份认证过程
- shiro身份认证
- shiro身份认证
- Shiro身份认证
- Shiro ---身份认证、授权
- Shiro身份认证
- 【shiro】--- 身份认证
- Shiro身份认证
- Shiro 的身份认证
- 【Shiro】Apache Shiro架构之身份认证(Authentication)
- 【Shiro】Apache Shiro架构之身份认证(Authentication)
- 【Shiro】Apache Shiro架构之身份认证(Authentication)
- Apache Shiro 身份认证例子
- Android 在一个activity中关闭其他activity
- elastic-job部署以及简单例子
- MongoDB数据库之数据的导入与导出
- 第一章 Shiro简介——《跟我学Shiro》
- PopupWindow弹出动态计算展示的位置,左、右、上、下对齐
- shiro身份认证(第一章)
- qt 中获取鼠标位置
- zeit/micro Error -- Cannot find module '../lib/help'
- IPTV工作原理
- 关于ArcGis的.geodatabase离线地图不能正确显示中文标记的解决办法
- [剑指offer]面试题10:二进制中1的个数
- 使用TCP协议编写一个网络程序,设置服务器程序监听端口为8002,当与客户端建立连接后,向客户端发送“hello world”,客户端接负责将信息输出
- Makefile十二之make的运行
- FWFWE