Shiro(四):Shiro 多Realm验证和认证策略

Shiro(三)介绍Shiro 密码的比对与MD5盐值加密,接下来对 多Realm验证和认证策略进行简单的介绍。

存在这样一种场景,我们可能会把安全数据放到不同的数据库,比方说 mysql里有,oracle里也有,mysql里面的加密算法是MD5,oracle里面的加密算法是SHA1。这个时候我们进行用户认证时,就需要同时访问这两个数据库,就需要多个Realm。如果有多个Realm的话,还需要涉及到认证策略的问题。

一、多Realm验证(方式一)

多重认证,主要的类是ModularRealmAuthenticator,他有两个需要配置的属性,一个是Collection(用于存储Realm),另一个是AuthenticationStrategy(用于存储验证的策略 )。

通过查看源码可以看到 ModularRealmAuthenticator.class 中的 doAuthenticate

    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
   
        assertRealmsConfigured();
        Collection<Realm> realms = getRealms();
        if (realms.size() == 1) {
   //一个realm
            return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
        } else {
   //多个realm
            return doMultiRealmAuthentication(realms, authenticationToken);
        }
    }

从上面doAuthenticate方法中可以看到:

  • 如果有一个Realm 使用的是
    doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);

  • 如果有多个Realm 使用的是
    doMultiRealmAuthentication(realms, authenticationToken);

所以我们可以配置多个Realm 给到 ModularRealmAuthenticator 这个bean,将ModularRealmAuthenticator 单独配置为一个bean,将这个bean 配置给SecurityManager。

配置流程:

1.添加第二个Realm SecondRealm.java

SecondRealm.java 中的 加密算法 为 SHA1

package com.example.shiro.realms;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;

public class SecondRealm extends AuthenticatingRealm{
   

	/**
	 * 认证 
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
   
		System.out.println("[SecondRealm] doGetAuthenticationInfo:"+token);
		//1.把AuthenticationToken 转换称 UsernamePasswordToken
		UsernamePasswordToken upToken =(UsernamePasswordToken) token;
		//2.从UsernamePasswordToken中获取用户名
		String username=upToken.getUsername();
		//3.调用数据库方法,从数据库中查询username对应的用户记录
		System.out.println("从数据库中获取username:"+username+"对应的用户信息");
		//4.判断用户是否存在,若不存在,则抛出UnknownAccountException异常
		if("unknown".equals(username)){
   
			throw new UnknownAccountException("用户不存在!");
		}
		//5.根据用户信息的情况,决定是否需求抛出其他的AutheticationException异常。如用户锁定等
		if("monster".equals(username)){
   
			throw new LockedAccountException("用户被锁定!");
		}
		//6.根据用户的情况,来构建AuthenticationInfo对像并返回,通常使用的实现类是SimpleAuthenticationInfo
		//以下信息是从数据库获取的
		//1).principal:认证的实体类信息。可以是username,也可以是数据表对应的用户的体类对象
		Object principal=username;
		//2).credentials:密码(数据库获取的用户的密码)
		Object credentials=null;//"fc1709d0a95a6be30bc5926fdb7f22f4";
		if(username.equals("admin")){
   
			credentials = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";//由下面的main方法对应不同的盐值得到
		}else if(username.equals("user")){
   
			credentials = "073d4c3ae812935f23cb3f2a71943f49e082a718";
		}
		//3).realmName:当前realm对象的name,调用父类的getName()方法即可
		String realmName=getName();
		//4).盐值
		ByteSource credentialsSalt = ByteSource.Util.bytes(username);//盐值 要唯一
		
		//SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal, credentials, realmName);
		SimpleAuthen
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值