6.Shiro授權_前提

1.前提:前邊學多realm的時候,使用一個認證器authenticator,同時該認證器會配置到securityManager的bean下,代碼如下:
<bean id="securityManager"  class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="authenticator" ref="authenticator"/>
</bean>
<!-- 多realm認證器 -->
     <bean id="authenticator"  class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
           <property name="realms">
                <list>
                     <ref bean="jdbcRealm"/>
                     <ref bean="secondRealm"/>
                </list>
           </property>
           <!-- 修改認證策略 -->
           <property name="authenticationStrategy">
                <bean  class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"/>
           </property>
     </bean>
 
但是我們在做授權的時候需要從securityManager中獲取realms,所以這裏我們需要修改一下realms屬性的配置代碼如下:
<bean id="securityManager"  class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <--authenticator需要配置在realms之前-->
    <property name="authenticator" ref="authenticator"/>
    <property name="realms">
        <list>
            <ref bean="jdbcRealm"/>
            <ref bean="secondRealm"/>
        </list>
    </property>
</bean>
<!-- 多realm認證器 -->
<bean id="authenticator"  class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
    <!-- 修改認證策略 -->
    <property name="authenticationStrategy">
        <bean  class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"/>
    </property>
</bean>
 
 
這裏有幾個問題需要我們知道:
問題1:爲什麼要使用這種方式?
回答:因爲授權時需要從securityManager中獲取realms,所以一般使用此方式配置多realm
問題2:爲什麼這種方式使用沒問題?
回答:參考問題3
問題3:實際調用是使用的是SecurityManager的realms,還是ModularRealmAuthenticator的realms?
回答:在自定義realm中打斷點,當程序停下時向上翻到DefaultWebSecurityManager是可以看到,在SecurityManager認證時調用的是ModularRealmAuthenticator的authenticator()方法,需要用到realms的時候,調realms的是ModularRealmAuthenticator在IOC容器中注入時realms是配給SecurityManager的,而沒有配給ModularRealmAuthenticator,但是爲什麼ModularRealmAuthenticator的realms會有值?原因就在於在啓動項目時,AuthenticatingSecurityManager的afterRealmsSet()方法把SecurityManager的authenticator屬性裏面的值set到ModularRealmAuthenticator的realms裏。
代碼:((ModularRealmAuthenticator)authenticator).setRealms(getRealms());
簡單的理解就是SecurityManager獲取到(ModularRealmAuthenticator)authenticator屬性和(Collection)realms屬性,在SecurityManager的一個方法中(afterRealmsSet)再把realms放到(ModularRealmAuthenticator)authenticator的realms裏
 
問題4:爲什麼authenticator屬性要配置在realms之前?
回答:因爲這涉及是先setAuthenticator()還是setRealms()的問題,
正常應該先setAuthenticator()setRealms(),這是因爲setAuthenticator()方法注入的是上面配置的多realm認證器,在IOC容器中我們可以看到此時realms已經不在這裏配置了,所以ModularRealmAuthenticator的realms屬性爲null,下面代碼debug中也可以看到。
所以先配置authenticatorsetAuthenticator()方法中realms屬性爲null
後配置realmssetRealms()的中會把realms屬性設置回來。
如果配置相反,則配置了realms屬性之後,setAuthenticator()方法中又把realms屬性置爲null
因此導致異常:
java.lang.IllegalStateException: Configuration error:  No realms have been configured!  One or more realms must be present to execute an authentication attempt.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章