Shiro的Relam主要作用是就是数据交互了,本质上相当于一个Dao。
多数Relam都会继承自AuthorizingRealm(自主实现AuthorizingRealm会很耗时)。
Shiro的Relam是验证的具体实现类;而Authentication是验证的通用组件,最终还要低啊用Relam来实现验证。
Relam的配置可以是隐式,也可以是显式。(shiro.ini)
显式配置:
fooRealm = com.company.foo.Realm
barRealm = com.company.another.Realm
bazRealm = com.company.baz.Realm
securityManager.realms = $fooRealm, $barRealm, $bazRealm
隐式配置:
blahRealm = com.company.blah.Realm
fooRealm = com.company.foo.Realm
barRealm = com.company.another.Realm
# no securityManager.realms assignment here
Shiro将自动按照Relam的定义顺序来完成securityManager.relams的初始化。(改变定义顺序会导致整个验证流程变化,所以,一般不建议隐式配置)
Relam的验证过程(UsernamePasswordTokens验证模式不支持的情况下,要使用AuthenticationToken。所以会调用Relam的getAuthenticationInfo(token)方法来进行处理):
1.检查token中的验证属性完整性;
2.根据token中信息查找数据源;
3.确认数据源中所得数据与验证数据完全一致;
4.验证匹配成功,将验证信息以固定格式封装交给Shiro;
5.验证匹配失败,抛出AuthenticationException异常。
自定义Relam及matcher(匹配器)
代码中添加:
Realm myRealm = new com.company.shiro.realm.MyRealm();
CredentialsMatcher customMatcher = new com.company.shiro.realm.CustomCredentialsMatcher();
myRealm.setCredentialsMatcher(customMatcher);
配置文件中添加(shiro.ini):
[main]
...
customMatcher = com.company.shiro.realm.CustomCredentialsMatcher
myRealm = com.company.shiro.realm.MyRealm
myRealm.credentialsMatcher = $customMatcher
...
Shiro默认matcher是SimpleCredentialsMatcher。
Shiro提供了HashedCredentialsMatcher,用以处理加密过的数据匹配。
对信息加密
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
...
//We'll use a Random Number Generator to generate salts. This
//is much more secure than using a username as a salt or not
//having a salt at all. Shiro makes this easy.
//
//Note that a normal app would reference an attribute rather
//than create a new RNG every time:
RandomNumberGenerator rng = new SecureRandomNumberGenerator();
Object salt = rng.nextBytes();
//Now hash the plain-text password with the random salt and multiple
//iterations and then Base64-encode the value (requires less space than Hex):
String hashedPasswordBase64 = new Sha256Hash(plainTextPassword, salt, 1024).toBase64();
User user = new User(username, hashedPasswordBase64);
//save the salt with the new account. The HashedCredentialsMatcher
//will need it later when handling login attempts:
user.setPasswordSalt(salt);
userDAO.create(user);
创建1024散列迭代增强安全性( 具体在HashedCredentialsMatcher的帮助文档中查看)
[main]
...
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
# base64 encoding, not hex in this example:
credentialsMatcher.storedCredentialsHexEncoded = false
credentialsMatcher.hashIterations = 1024
# This next property is only needed in Shiro 1.0. Remove it in 1.1 and later:
credentialsMatcher.hashSalted = true
...
myRealm = com.company.....
myRealm.credentialsMatcher = $credentialsMatcher
...
最后,返回SaltedAuthenticationInfo验证信息。