shiro小记
shiro: 流程: 初始化SecurityManager工厂 => 获取SecurityManager => 获取subject => 根据用户名密码创建token => subject.login(token)验证 => 调用自定义的realms: 实现AuthorizingRealm自定义的realms验证流程: 实现doGetAuthenticationInfo(token)方法获取AuthenticationInfo对象 => 通过CredentialsMatcher对象doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)方法验证AuthenticationInfo subject.login(token)调用时发生了什么? 从源码可以得知Subject是接口,实现该接口的类有: Subject(接口): DelegatingSubject(实现类):从源码可以得知是subject默认实现,因为有login(token)方法 WebDelegatingSubject(实现类): DelegatingSubject.login():方法会调用securityManager.login(this, token)方法; 调用此方法中最重要的一个过程是调用new 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); } } 从以上方法可以看出 getRealms()获取我们自定义配置的realms,然后依次调用 1.========主要接口========= securityManager: 主要方法: Subject login(Subject subject, AuthenticationToken authenticationToken) throws AuthenticationException; void logout(Subject subject); Subject createSubject(SubjectContext context); Realm: 主要方法: String getName(); boolean supports(AuthenticationToken token); AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; CredentialsMatcher: 主要方法: boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info); 2.=====主要接口的实现关系======= 实现securityManager接口实现关系: securityManager: CachingSecurityManager(抽象实现类): RealmSecurityManager(抽象实现类): AuthenticatingSecurityManager:(抽象实现类) AuthorizingSecurityManager(抽象实现类): SessionsSecurityManager(抽象实现类): DefaultSecurityManager(实现类): 实现Realm接口实现关系: Realm(接口) CachingReaml(抽象类):只是添加了cacheManager属性并没有实现Realm接口方法 AuthenticatingRealm(抽象类):实现了Realm接口getAuthenticationInfo(AuthenticationToken token)方法并定义为final类型,也就是说从该层开始以下的类不能在重写该方法只能重写新引入doGetAuthenticationInfo(token)抽象方法获取AuthenticationInfo对象;引入CredentialsMatcher接口对象,通过调用该对象的doCredentialsMatch(token, info)方法实现验证;(回调函数) 注意:/**getAuthenticationInfo方法定义为final,不能被重写**/ 啰嗦这么多总结一句话:就是AuthenticatingRealm类已经对getAuthenticationInfo(AuthenticationToken token)方法定制好了业务逻辑,只需要实现里面的细节 AuthorizingRealm(抽象类):doGetAuthenticationInfo(token)实现该方法,实现自己的业务逻辑 实现CredentialsMatcher接口实现关系: CredentialsMatcher: AllowAllCredentialsMatcher(实现类):doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) return true; 所有都通过验证 PasswordMatcher(实现类):该类有passwordService对象,通过passwordService.passwordsMatch(submittedPassword, formatted)实现加密密码的验证; SimpleCredentialsMatcher(实现类):简单的身份验证 3.=======关联的一些重要接口========== PasswordService(接口): 主要方法: //顾名思义对密码加密 String encryptPassword(Object plaintextPassword) throws IllegalArgumentException; //加密密码的验证 boolean passwordsMatch(Object submittedPlaintext, String encrypted); 实现关系: HashingPasswordService(接口):实现PasswordService DefaultPasswordService(实现类):默认:DEFAULT_HASH_ALGORITHM = "SHA-256" 总结: 实现自定义realm: 1)实现Realm接口,实现简单的自定义realm 2)继承AuthorizingRealm(抽象类),实现doGetAuthenticationInfo(token)方法,可以给自定义的realm设置CredentialsMatcher接口对象,如果不设置默认为SimpleCredentialsMatcher; 如果想对密码加密需要设置PasswordMatcher接口,该对象默认使用DefaultPasswordService(PasswordService接口对象); 也可以自定义PasswordService接口对象并传入,这样就可以按照自己的需求去加密密码,以及验证密码; 继承AuthorizingRealm(抽象类)可以实现从缓存中取AuthenticationInfo: 由源代码可以得知AuthenticatingRealm有以下属性: //用于密码验证,登录的明文密码与加密后的密码是否匹配 private CredentialsMatcher credentialsMatcher; //使用缓存技术从缓存中获取AuthenticationInfo private Cache<Object, AuthenticationInfo> authenticationCache; //是否使用缓存获取AuthenticationInfo private boolean authenticationCachingEnabled; //获取名称 private String authenticationCacheName; ==========主要方法介绍============ public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //从缓存中获取AuthenticationInfo 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; }
想的都是好