Shiro多個Realm認證及授權

解決方案如下:

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章