解決方案如下:
首先自定義一個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,畢竟是多個分割成單個去校驗,還請大家多多指教。