关于Shiro中的Realm

前言

  最近看关于Shiro的一些文章,看的有点一头雾水。看了看源码,又看了看文章,把自己的理解的记录一下。
(看的文章:跟我学Shiro目录贴 。有兴趣的可以看一下,这里的例子来自于这些文章)


正文

Realm能做的工作主要有以下几个方面:

  • 验证是否能登录,并返回验证信息(getAuthenticationInfo方法)
  • 验证是否有访问指定资源的权限,并返回所拥有的所有权限(getAuthorizationInfo方法)
  • 判断是否支持token(例如:HostAuthenticationToken,UsernamePasswordToken等)(supports方法)

这里主来说明一下关于前两点验证方面的逻辑。

1,验证是否能登录,并返回验证信息

首先先看一下Realm接口的内容,这个接口里有3个方法,内容如下:

  • AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
  • boolean supports(AuthenticationToken token)
  • String getName()

我们看到第一个方法就是我们上面说的“验证是否能登录,并返回验证信息”的方法。从方法的名字上看,只有取得验证信息的意思,其实这里面还包括了进行验证的逻辑。
看Javadoc,这个方法的作用是“根据传进来的Token,返回用户的验证信息”。下面说明一下“Token”和“用户验证信息”。

  • Token:就是要拿来进行验证的信息,例如:如果是UsernamePasswordToken的话,这个Token的内容就是“用户提交的用户名和密码”。
  • 用户验证信息:就是用户验证通过后,返回给系统的信息。例如:用户登录验证的话,一般来说,返回给系统的“用户验证信息”就应该是这个用户的“用户名和密码”。但也可以返回其它信息,例如返回用户的“邮箱地址和登录密码”信息,做为“用户验证信息”。
    (具体什么情况下需要这么做还不知道,可能在多系统通过同一点进行登录,但由于历史原因,每个系统使用的用户信息不一致(有的使用uid,有的使用邮箱)时,使用吧)。

上面说了“根据传进来的Token”和“返回用户的验证信息”,但没有说验证的过程,这个过程也是在这个方法中进行。我们看一下源码:

public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

    AuthenticationInfo info = getCachedAuthenticationInfo(token);
    // doGetAuthenticationInfo方法的内容,由各个子类来实现。
    // 主要是用来取得我们保存的“用户验证信息”,例如DB里保存的密码(具体看JdbcRealm的方法实现)
    if (info == null) {
        info = doGetAuthenticationInfo(token);
        ...
    }
    // 在这里,把用户提交的信息(Token)和我们保存的“用户验证信息”进行比较
    // 如果不通过,直接抛出定义好的异常。
    if (info != null) {
        assertCredentialsMatch(token, info);
    } else {

    return info;
}


2,验证是否有访问指定资源的权限,并返回所拥有的所有权限

  “验证是否登录”的处理,是由接口定义的。但“验证是否有访问权限”的逻辑,则是由类定义的。定义的类为:AuthorizingRealm ,在这个类中有个getAuthorizationInfo 方法。这个方法和getAuthenticationInfo 方法的处理流程有点像:

  • 验证是否有指定的权限
  • 返回用户的权限信息

同样,这个方法里面也包含了“验证”逻辑。


3,实现自定义Realm

  从上面的功能说明可以看出来,在权限控制中比较重要的验证(登录或权限)逻辑,都是在Realm中做的。Realm的类继承如下:
Realm类继承图


继承了AuthorizingRealm的类,都要实现上面说的getAuthenticationInfo和getAuthorizationInfo方法,来完成登录和权限的验证。但如果自定义的Realm类只实现Realm接口的话,只需要getAuthenticationInfo方法就可以。下面看一个只实现Realm接口的自定义Realm。

public class MyRealm1 implements Realm {  
    @Override  
    public String getName() {  
        return "myrealm1";  
    }  
    @Override  
    public boolean supports(AuthenticationToken token) {  
        //仅支持UsernamePasswordToken类型的Token  
        return token instanceof UsernamePasswordToken;   
    }  
    @Override  
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  
        String username = (String)token.getPrincipal();  //得到用户名  
        String password = new String((char[])token.getCredentials()); //得到密码  
        if(!"zhang".equals(username)) {  
            throw new UnknownAccountException(); //如果用户名错误  
        }  
        if(!"123".equals(password)) {  
            throw new IncorrectCredentialsException(); //如果密码错误  
        }  
        //如果身份认证验证成功,返回一个AuthenticationInfo实现;  
        return new SimpleAuthenticationInfo(username, password, getName());  
    }  
}   

在上面的自定义Realm中,我们可以看到getAuthenticationInfo方法的实现。在这里,把用户名和密码都写死了,只为了简单的呈现上面说的逻辑。登录验证通过后,必须要返回一个AuthenticationInfo类型的实例。


  为什么要返回AuthenticationInfo 呢?框架里,最后把返回的AuthenticationInfo 保存到了SecurityManager里了,可能是为了以后在某些地方使用,还没有深入去看。
 
 
 
 
 
 
 
 
  
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值