Realm是shiro比较核心的接口,简单说它的实现类就是校验用户输入的账号信息的地方.如果想自定义实现一般的配置文件如下:
<!--自定义Realm 继承自AuthorizingRealm -->
<bean id="userRealm" class="xxx.UserRealm">
<!-- 自定义比对器 -->
<property name="credentialsMatcher" ref="myCredentialsMatcher"></property>
</bean>
<!-- 自定义匹配器 继承自SimpleCredentialsMatcher -->
<bean id="myCredentialsMatcher" class="xxx.MyCredentialsMatcher"></bean>
其中类的关键代码:
public class UserRealm extends AuthorizingRealm { public UserRealm() {
super();
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//这里返回的就是你自定义Token中getPricipal返回的用户信息对象.
Object user = principals.getPrimaryPrincipal();
......
return authorizationInfo; } @Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
Object user = authcToken.getPrincipal();
//从数据库中查找用户的信息
UserInfo info = Dao.selectUser(user);
...
//按照用户的输入的principal信息去数据库中查询,然后封装出比对信息.下面的info.getPwd()代表的就是Credentials信息,一般指的密码
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, info.getPwd(), getName());
return authenticationInfo;
}
//自定义matcher,这里就是对比用户的输入的信息封装成的token和按照用户输入的principal(一般就是用户名)从数据库中查询出的信息封装的info信息,一般就是比对他们的Credentials
public class MyCredentialsMatcher extends SimpleCredentialsMatcher { @Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = getCredentials(token);
Object accountCredentials = getCredentials(info);
return super.equals(tokenCredentials, accountCredentials);
}
}
这里红色的doGetAuthenticationInfo方法是用来按照用户输入的principal信息从数据库中查询,并将结果作为一个比对信息,比对2者的Credentials信息是否一致,比对时将调用比对器的doCredentialsMatch方法进行比对,所以我们可以在realm中配置自定义的比对器,重写此方法来达到自定义比对方法,实现特殊的比对逻辑.尤其是token中封装自定义对象时
.如果一致则登录成功.而绿色的doGetAuthorizationInfo方法则是作为获取当前用户的角色权限相关信息的方法,此方法中要根据用户信息查询出相关的角色权限信息并封装进去.有了此信息之后就可以根据角色和权限信息进行访问权限的控制了.
一般直接使用usernamePasswordToken即可,但是由于此默认实现一般存储的为字符串的principal和Credentials信息,如有必要改为存储自定义对象,则可以自定义token来实现,关键代码:
/* 这里必须说一下,必须要继承UsernamePasswordToken,因为realm实现中有个suports方法,会判断token是否被支持,默认的情况下是只支持UsernamePasswordToken的.如需要完全自定义,则需要单独再realm配置中添加上新的自定义token的类型支持. */
public class MyUserToken extends UsernamePasswordToken {
//这个自定义的属性可以是对象.
private Object user; public MyUserToken() {
} public MyUserToken(Objectuser) {
this.user = user;
}
@Override
public Object getPrincipal() {
//账号信息
return user;
} @Override
public Object getCredentials() {
//校验的信息,其实一般就是指密码
return user.getPwd();
} }
在用户登录时关键代码:
Subject currentUser = SecurityUtils.getSubject();
UserInfo user = new UserInfo();
user.setName("aaa");
user.setPwd("123");
MyUserToken token = new MyUserToken(user);
currentUser.login(token);
if (currentUser.isAuthenticated()) {
//登录成功
}else{
//失败
}
总体的思路为使用自定义的token类将用户输入的信息封装,然后采用token进行login操作.此时shiro将使用token中携带的用户信息调用Realm中自定义的doGetAuthenticationInfo方法进行校验比对.比对成功则登录成功,并会自动将相关角色权限信息封装进去.