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

	 
	 
	

 

posted @ 2017-12-26 14:09  少年已不在年少  阅读(201)  评论(0编辑  收藏  举报