这个接口是用来实现rememberme的功能的。他的实现类为AbstractRememberMeManager,是一个抽象类,最终的继承类为cookieRememberMeManager,即将信息发送到cookie中。
先看一下defaultWebSecurityManager的构造方法:
public DefaultWebSecurityManager() {
super();
((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());
this.sessionMode = HTTP_SESSION_MODE;
setSubjectFactory(new DefaultWebSubjectFactory());
setRememberMeManager(new CookieRememberMeManager());//初始化一个cookieRememberMeManager。
setSessionManager(new ServletContainerSessionManager());
}
我们从AbstractRememberMeManager的源码开始看。
这个类中有两个重要的属性:
1、Serializer<PrincipalCollection> serializer; //用来将subject的principalCollection转化为byte[] 数组的。使用的实现类是DefaultSerializer,里面的逻辑是使用标准的jvm序列化方式来实现的。
2、CipherService cipherService;这个属性用来将序列化的字符串数组进行加密的,我们简单的看一下他的javadoc:他通过一种加密方法(Cipher)将输入的值转化为一个不可读的模式(加密),但是这个转化过程必须使用一个key。这个转化过程是可逆的,但是在逆转化(解密)的时候必须也要知道这个key才可以。CipherService类可以实现加密和解密两个功能。
Cipher分为对称加密和非对称加密,对称加密指的是对于加密和解密的key是一样的,非对称加密是指加密和解密的key是不一样的。(对于这些个加密算法我也没有研究)
因为我们最终使用的CipherService是AesCipherService,他是一个对称加密的,所以使用的key只有一个,在AbstractRememberMeManager中统一使用byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");作为加密和解密的key。
在构造方法有一个方法:setCipherKey,就是将byte[]设置为encryptionCipherKey和decryptionCipherKey。所以这样就可能早成一个问题,我们的最终实现是将pricipalCollection作为cookie的value发送到cookie中取得,如果有人知道我们使用的是shiro,并且知道我们使用的是对称的AesCipherService进行对称加密解密并且使用的key是Base64.decode("kPH+bIxk5D2deZiIxcaaaA=="),那么就可以通过解密来获得之前设置的principalCollection,在AbstracRememberMeManager的javadoc中也提及了,如果我们的principalCollection