實現多Realm時,可能會出現的問題


問題背景 
在實現多Realm時,擴展了ModularRealmAuthenticator 和 UsernamePasswordToken,於是在MyAuthenticationToken token = (MyAuthenticationToken) authenticationToken時出現了轉型異常。

擴展ModularRealmAuthenticator 的代碼如下:

public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {

    @Override
    public AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        MyAuthenticationToken token = (MyAuthenticationToken) authenticationToken;
        String loginType = token.getLoginType();
        Collection<Realm> realms = getRealms();
        Collection<Realm> authRealms = new ArrayList<>();
        for(Realm realm : realms){
            if(realm.getName().equals(loginType)){
                authRealms.add(realm);
            }
        }

        if(authRealms.size() == 1){
             return doSingleRealmAuthentication(authRealms.iterator().next(), token);
        } else {
            return doMultiRealmAuthentication(authRealms, token);
        }
    }

}

擴展UsernamePasswordToken的代碼如下:

public class MyAuthenticationToken extends UsernamePasswordToken {

    private String loginType;

    public MyAuthenticationToken(final String username, final String password, String loginType){
        super(username, password);
        this.loginType = loginType;
    }

    public String getLoginType() {
        return loginType;
    }

    public void setLoginType(String loginType) {
        this.loginType = loginType;
    }
}

從上面的擴展中我們看到,沒有地方使用我們的自己擴展的MyAuthenticationToken類,只是轉型而已,並沒有去實例化它,這才是引起問題的根源,問題發現了要如何解決它呢?我們在配置的使用並並未制定表單過濾器,此時默認使用的是FormAuthenticationFilter,而Token默認使用的也是UsernamePasswordToken,由此看來,我們擴展的MyAuthenticationToken就成了擺設,此時就要想辦法如何將我們的擴展引用到程序里去呢? 
既然默認的是UsernamePasswordToken,那么是如何將UsernamePasswordToken注入的呢?我們進入默認的Filter(FormAuthenticationFilter)可以看到createToken,這個是創建Token的,那么似乎可以和我們的Token搭上邊了,FormAuthenticationFilter中的createToken如下:

protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = this.getUsername(request);
        String password = this.getPassword(request);
        return this.createToken(username, password, request, response);
}

我們發現期間又調用了createToken,此createToken為父類的方法,我們可以看到FormAuthenticationFilter的聲明為 public class FormAuthenticationFilter extends AuthenticatingFilter ,也即內部調用的token為AuthenticatingFilter的實現,繼續看AuthenticatingFilter中的createToken實現,而createToken中又調用了自身createToken的重載,源碼如下:

protected AuthenticationToken createToken(String username, String password, ServletRequest request, ServletResponse response) {
        boolean rememberMe = this.isRememberMe(request);
        String host = this.getHost(request);
        return this.createToken(username, password, rememberMe, host);
    }

    protected AuthenticationToken createToken(String username, String password, boolean rememberMe, String host) {
        return new UsernamePasswordToken(username, password, rememberMe, host);
    }

可以看到在重載的createToken中,UsernamePasswordToken終於現身了,那么此時,我們可以通過擴展FormAuthenticationFilter並重新createToken將我們擴展的Token引入即可,以下為擴展的FormAuthenticationFilter:

public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    @Override
    protected MyAuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);
        String password = getPassword(request);
        String loginType = request.getParameter("loginType");
        if("sys".equals(loginType)){
            return new MyAuthenticationToken(username, password, "sys");
        } else {
            return new MyAuthenticationToken(username, password, "wx");
        }
    }

}

擴展完成后,需要配置默認的過濾器為我們的擴展,shiro的配置如下:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/login" />
        <property name="successUrl" value="/index"/>
        <property name="unauthorizedUrl" value="/403"/>
        <property name="filterChainDefinitions">
            <value>
                /favicon.ico = anon
                /logout = logout
                /** = authc
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="authc" value-ref="myFormAuthenticationFilter" />
            </map>
        </property>
    </bean>

    <bean id="myFormAuthenticationFilter" class="com.yuxiao.springboot.springbootmybatis.config.shiro.filter.MyFormAuthenticationFilter"/>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM