自定义shiro的Realm实现和CredentialsMatcher实现以及Token实现

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方法进行校验比对.比对成功则登录成功,并会自动将相关角色权限信息封装进去.

posted on 2016-10-13 23:45  蓝萝卜blu  阅读(12793)  评论(0编辑  收藏  举报

导航