解决方案如下:
首先自定义一个DefaultUsernamepasswordToken.java,继承Shiro自带的UsernamePasswordToken,在DefaultUsernamepasswordToken中新加一个属性
private String loginType; 而后生成getter setter;
public class DefaultUsernamepasswordToken extends UsernamePasswordToken {
/**
* 判断登录类型
*/
private String loginType;
public String getLoginType() {
return this.loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
/**
* Shiro 构造方法
*
* @author : tanzhen
* @date :2016年7月28日
*/
public DefaultUsernamepasswordToken(String username, String password) {
super(username, password);
}
public DefaultUsernamepasswordToken() {
}
}
然后自定义一个DefautModularRealm.java,继承 ModularRealmAuthenticator,重写doMultiRealmAuthentication、doSingleRealmAuthentication、doAuthenticate、assertRealmsConfigured四个方法,还需要定义一个变量,
用来接收传进来的多个Realm。
public class DefaultModularRealm extends ModularRealmAuthenticator {
private Map<String, Object> definedRealms;
/**
* 多个realm实现
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(
Collection<Realm> realms, AuthenticationToken token) {
return super.doMultiRealmAuthentication(realms, token);
}
/**
* 调用单个realm执行操作
*/
@Override
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,
AuthenticationToken token) {
// 如果该realms不支持(不能验证)当前token
if (!realm.supports(token)) {
throw new ShiroException("token错误!");
}
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
if (info == null) {
throw new ShiroException("token不存在!");
}
} catch (Exception e) {
throw new ShiroException("用户名或者密码错误!");
}
return info;
}
/**
* 判断登录类型执行操作
*/
@Override
protected AuthenticationInfo doAuthenticate(
AuthenticationToken authenticationToken)
throws AuthenticationException {
this.assertRealmsConfigured();
Realm realm = null;
DefaultUsernamepasswordToken token = (DefaultUsernamepasswordToken) authenticationToken;
if (token.getLoginType().equals("huimai")) {
realm = (Realm) this.definedRealms.get("defaultJdbcRealm");
}
if (token.getLoginType().equals("shiro")) {
realm = (Realm) this.definedRealms.get("shiroDbRealm");
}
if (realm == null) {
return null;
}
return this.doSingleRealmAuthentication(realm, authenticationToken);
}
/**
* 判断realm是否为空
*/
@Override
protected void assertRealmsConfigured() throws IllegalStateException {
this.definedRealms = this.getDefinedRealms();
if (CollectionUtils.isEmpty(this.definedRealms)) {
throw new ShiroException("值传递错误!");
}
}
public Map<String, Object> getDefinedRealms() {
return this.definedRealms;
}
public void setDefinedRealms(Map<String, Object> definedRealms) {
this.definedRealms = definedRealms;
}
}
这里需要注意是 其实 流程是:在给DefaultUsernamepasswordToken赋值时,将loginType设置成相应的参数,然后在doAuthenticate时判断,单个调用对应的Realm。然后是xml文件配置:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 其他配置 -->
<property name="authenticator" ref="defineModularRealmAuthenticator" />
<property name="realms">
<list>
<ref bean="defaultJdbcRealm" />
<ref bean="shiroDbRealm" />
</list>
</property>
</bean>
<!-- -->
<bean id="defineModularRealmAuthenticator"
class="com.zynsun.platform.realm.DefaultModularRealm">
<property name="definedRealms">
<map>
<entry key="defaultJdbcRealm" value-ref="defaultJdbcRealm" />
<entry key="shiroDbRealm" value-ref="shiroDbRealm" />
</map>
</property>
<!-- <property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy" />
</property> -->
</bean>
<!-- -->
<bean id="defaultJdbcRealm" class="com.xxxx.shiro.DefaultRealm">
</bean>
<bean id="shiroDbRealm" class="com.xxx.shiro.ShiroRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"></property>
</bean>
利用SecurityManager来进行配置。这样就完成了多个Realm认证,其实这种也只能算是单个Realm,毕竟是多个分割成单个去校验,还请大家多多指教。