美文网首页
3. Shiro认证

3. Shiro认证

作者: 不知名的蛋挞 | 来源:发表于2019-08-21 18:40 被阅读0次

Shiro认证思路分析

之前将架构的时候说过,如果需要访问Shiro的安全数据的话,需要用Realm。所以我们需要用Realm获取数据库认证数据,而密码比对是由Shiro帮我们完成的。

  1. 获取当前的Subject,调用SecurityUtils.getSubject()
  2. 测试当前的用户是否已经被认证,即是否已经登录,调用Subject的isAuthenticated()
  3. 若没有被认证,则把用户名和密码封装为UsernamePasswordToken对象;
    1)创建一个表单页面
    2)把请求提交到SpringMVC的Handler
    3)获取用户名和密码
  4. 执行登陆:调用Subject的login(AuthenticationToken)方法
  5. 自定义Realm的方法,从数据库中获取对应的记录,返回给Shiro
    1)实际上需要继承org.apache.shiro.realm.AuthenticatingRealm
    2)实现doGetAuthenticationInfo(AuthenticationToken)方法
  6. 用shiro完成对密码的比对

【登录表单】

【Handler】

【Realm】

Handler中的token会传到Realm的doGetAuthenticationInfo方法中:

实现认证Realm

上面我们说到Handler中的token会传到Realm的doGetAuthenticationInfo方法中,所以我们可以将AuthenticationToken转换为UsernamePasswordToken

现在有登陆的验证了,我们再写一个登出。

logout表示登出的过滤器。

shiro密码的比对

密码的比对是由shiro完成的,那么shiro是怎么比对密码的呢?

查看源代码可以发现密码的比对是通过通过AuthenticatingRealm的CredentialsMathcer属性进行密码的比对。

密码加密

(1)密码的MD5加密

上面的代码中,密码的比对是通过明文直接比对的,这样显然是不安全的,我们应该对密码加密。如何进行密码的加密呢?也可以通过CredentialsMathcer完成。

如何把前端传过来的密码加密为MD5?这个时候就需要靠“凭证匹配器”CredentialsMathcer,我们需要替换当前Realm的CredentialsMathcer属性,把它替换成HashedCredentialsMathcer,并设置加密算法即可。

hashIterations可以指定加密的次数。

下面就是把“123456”加密1024次的结果:

此时还需要把数据库获取到的密码也进行MD5加密再传入SimpleAuthenticationInfo构造器当中:

(2)密码的MD5盐值加密

密码一样的话加密后的结果是一样的话,还是有不安全性的。我们希望即便是两个人的原始密码一样,加密之后的结果也不一样。这个时候可以加点作料:盐值。

实现步骤:
1)在doGetAuthenticationInfo方法返回值创建SimpleAuthenticationInfo对象的时候,需要使用SimpleAuthenticationInfo(principal,credentials,credentialsSalt,realName)构造器;
2)使用ByteSource.Util.byte()方法来计算盐值;
3)盐值需要唯一,一般使用随机字符串或 user id;
4)使用new SimpleHash(hashAlgorithmName,credentials,salt,hashIteratons)来计算盐值加密后的密码的值;

多Realm验证

在实际的开发中,我们可能会把不同的数据放在不同的数据库里面(比如mysql里面有,oracle里面也有),mysql里面的加密算法可能是MD5,而oracle的加密算法是RSA,这个时候进行用户验证的话需要同时访问这两个数据库,就需要多个Realm。如果有多个Realm的话还涉及到认证策略的问题。

我们再创建多一个Realm进行测试,这里使用到的加密算法就是SHA1:

然后把这第二个Realm配置到IOC容器中:

shiro认证策略

有多个Realm的情况下,怎么样才算是认证通过呢?这就涉及到认证策略。

认证策略实际上就是AuthenticationStrategy接口的实现。这个接口有三个默认是实现:

  • FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;
  • AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,将返回所有Realm身份验证成功的认证信息;
  • AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

默认用的是FirstSuccessfulStrategy。如果想要使用其他认证策略,可以像下面这样配置:

把Realm配置给SecurityManager

我们把authenticator里面的Realm配置删掉,直接配置在SecurityManager里面:

然后再次运行发现是没有问题的。为什么这样做没问题呢?为什么要这么改呢?因为在做授权的时候,我们需要SecurityManager去读Realm,所以需要把relms配置到SecurityManager中。

分析源码可以看到实际上即使把Realm配置在SecurityManager,SecurityManager最终也会把Realm传递给authenticator:

相关文章

网友评论

      本文标题:3. Shiro认证

      本文链接:https://www.haomeiwen.com/subject/yelrsctx.html