<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java學習

    java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經搬家了,新的地址是 http://www.javaly.cn 如果有對文章有任何疑問或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂園)指出,我會盡力幫助解決。一起進步

     

    淺談Acegi配置

    Acegi配置文檔
    作者:javafish(likunkun)
    Email:javafish@sunxin.org
    Acegi是基于Spring的一個開源的安全認證框架,現在的最新版本是1.04。Acegi的特點就是有很多的過濾器:不過我們也用不到這么 多的過濾器,只是可以把它們看作為一個個的模塊,在用的時候加上自己用的著的即可,由于認證的流程的方面比較復雜導致它的配置很復雜,如果能摸清它的工作 原理還是不太難.下面用比較順著人思維的流程過一遍
    這里只列出常用的過濾器和攔載器
    1. 過濾器:HttpSessionContextIntegrationFilter,authenticationProcessingFilter,BasicProcessingFilter,RememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter
    2. 攔截器:filterSecurityInterceptor(其實它是過濾器,不過把它放在這里更能說明它的功能),methodSecurityInterceptor
    看著上面的用紅色標出的過濾器是用來認證(表單和HTTP基本認證,當然還有別的不過這兩個比較長用)它們是資源訪問的入口.其它的過濾器是用來 輔助的:HttpSessionContextIntegrationFilter是用來把認證信息記錄到Session中的 RememberMeProcessingFilter是以cookie的形式來保存認證信息的. anonymousProcessingFilter是在匿名的時候(這時候是沒有認證信息的)給這個用戶分配一個匿名的認證信息, exceptionTranslationFilter總結一下異常并處理.在實際中選擇適合程序的即可.
    上面只是資源訪問的入口,真正保護資源的是這兩個攔截器:filterSecurityInterceptor,攔截URL的類(它是個過濾器)
    metohdSecurityInterceptor,攔截類中方法的調用,它們為什么要攔截呢?就是想在訪問或調用這些方法之前來判斷一下用戶是否有訪問或調用的權限,有就通過,沒有就踢出.
    除此之外,Acegi專門做了兩個管理器(實際上就是兩個類,為什么會用做這兩個管理器,因為認證和授權都有一些的操作,這就需要專門做兩個管理 器了):authenticationManager(class= org.acegisecurity.providers.ProviderManager),授權管理器accessDecisionManager (class=org.acegisecurity.vote.AffirmativeBased)
    說白了一個用于認證用戶,一個是用于權限的授于的
    先來說認證用戶,認證管理器有什么東西呢?只內置了一些提供者:這些提供者呢又是什么呢,他們是提供用戶的驗證身份信息的,比如從數據庫或配置文件里讀出 用戶名和密碼,在用戶的cookie里讀出身份信息(rememberMeProcessingFilter用到的[前面講了的,有印象吧]),或在 Session里讀出身份驗證信息(HttpSessionContextIntegrationFilter起作用的),這里我們只說一下從數據庫或配 置文件里讀出用戶名密碼來裝配驗證信息的,其它的配置類似可以找一下對應api在Spring里配置即可, daoAuthenticationProvider是數據庫的提供者class= org.acegisecurity.providers.dao.DaoAuthenticationProvider,而它提供的服務呢又有幾種,數 據庫和配置文件(這是Acegi的兩個默認的實現)當然也可以自己實現(實現userDetailsService接口就行)
    Java代碼 復制代碼
    1. <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">  
    2.         <property name="providers">  
    3.             <list>  
    4.                 <ref local="daoAuthenticationProvider"/>  
    5.             </list>  
    6.         </property>  
    7.     </bean>  
    8. <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">  
    9.         <!-- <property name="userDetailsService"><ref local="InMemoryDaoImpl"/></property> --><!-- 這里有兩種選擇 -->  
    10.         <property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>  
    11.     </bean>  

    如果用戶名和密碼在配置文件里可以用InMemoryDaoImpl,class= org.acegisecurity.userdetails.memory.InMemoryDaoImpl,在這個類的userMap里配置即可: javafish=java,ROLE_USER,配置了一個用戶名為javafish,密碼為java,用戶組為ROLE_USER的用戶,不過最常用 的還是數據庫的JDBC實現(兩個二選一)org.acegisecurity.userdetails.jdbc.JdbcDaoImpl里面需要 usersByUsernameQuery和authoritiesByUsernameQuery還有數據源dataSource(有人問為什么呢, userByUsernameQuery是用來通過用戶名來查密碼的,authoritiesByUsernameQuery是用來通過用戶名來查權限 的,查詢數據庫肯定的用數據源吧這個里是用的SpringFrameWork的DataSource)它們查詢的sql語句是有講究的,就是查密碼的時候 查三個第一個是username,第二個是password,第三個是是否可用,查權限的時候查兩個:username和authorities(具體看 例子)
    Java代碼 復制代碼
    1. <bean id="InMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">  
    2.         <property name="userMap">  
    3.             <value>  
    4.                 javafish=java,ROLE_USER  
    5.             </value>  
    6.         </property>  
    7.     </bean>  
    8.     <bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">  
    9.         <property name="usersByUsernameQuery">  
    10.             <value>select username,password,enabled from users where username=?</value>  
    11.         </property>  
    12.         <property name="authoritiesByUsernameQuery">  
    13.             <value>select username,authority from authorities where username=?</value>  
    14.         </property>  
    15.         <property name="dataSource">  
    16.             <ref local="dataSource"/>  
    17.         </property>  
    18.     </bean>  
    19.       
    20.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    21.         <property name="driverClassName">  
    22.             <value>com.mysql.jdbc.Driver</value>  
    23.         </property>  
    24.         <property name="url">  
    25.             <value>jdbc:mysql://localhost:3306/test</value>  
    26.         </property>  
    27.         <property name="username">  
    28.             <value>root</value>  
    29.         </property>  
    30.         <property name="password">  
    31.             <value>javafish</value>  
    32.         </property>  
    33.     </bean>  

    下面說一下授權,授權管理器又有什么東西呢?accessDecisionManager,Acegi把授權方面弄的比較的形象化,把某個URL或方法是否可以被訪問按投票的形式來決定,

    Acegi提出來了幾種方案:
    1. 如果有一個贊成就同意(具體的說就是只要你在那個URL對應的幾個用戶組中的一個就讓你訪問)
    2. 如果都贊成就同意(具本的說就是那個URL對應的幾個用戶組里都有你,你才能訪問)
    3. 如果都不反對就同意(這個在下面講投票者的時候再說)
    Java代碼 復制代碼
    1. <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">  
    2.         <property name="allowIfAllAbstainDecisions"><!-- 是否讓全部棄權的通過 -->  
    3.             <value>false</value>  
    4.         </property>  
    5.         <property name="decisionVoters"><!-- 投票者們 -->  
    6.             <ref bean="roleVoter"/>  
    7.         </property>  
    8.     </bean>  

    而投票者呢:Acegi自己實現了一個投票者的類RoleVoter:
    現在我用第一種方案,RoleVoter只是在URL對應的用戶組里有ROLE_為前綴的才進行投票,否則的話棄權.(我們也可以在配置 RoleVoter的時候把ROLE_配置成為別的前綴如JAVA_),分別對URL對應的每個用戶組投票,如果用戶在這個用戶組里就投贊成,不在投反對 (在用戶組的前綴是ROLE_的前提下)這樣就不難體會第三種方案的用途了吧
    Java代碼 復制代碼
    1. <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">  
    2.         <property name="rolePrefix">  
    3.             <value>ROLE_</value><!-- 可以改成別的 -->  
    4.         </property>  
    5.     </bean>  

    這樣認證管理器和授權管理器就ok了,別的無論是過濾器還是攔截器都會用到它們兩個,因為它們都要驗證而這兩個就是憑證.
    那么那兩個訪問過濾器呢,先說authenticationProcessingFilter是用于表單登陸的
    Java代碼 復制代碼
    1. <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">  
    2.         <property name="authenticationManager"><ref bean="authenticationManager"/></property>  
    3.         <property name="authenticationFailureUrl"><value>/failure.html</value></property><!--登陸失敗轉向的頁面  -->  
    4.         <property name="defaultTargetUrl"><value>/ok.html</value></property><!-- 登陸成功轉向的頁面 -->  
    5.         <property name="filterProcessesUrl"><value>/check</value></property><!-- 要驗證的地址 -->  
    6.     </bean>  

    這樣的話加上上面配置的認證管理器就已經可以處理登陸了(注意的是它沒有用到授權管理器,因為它只是個訪問入口還沒有權限的授予)
    再說一下HTTP基本認證:它比上面的略復雜一點
    需要配置一個
    Java代碼 復制代碼
    1. <bean id="BasicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">  
    2.         <property name="realmName"><value>javafish</value></property><!-- 基本認證對話框上顯示的字 -->  
    3.     </bean>  
    4. 然后  
    5. <bean id="BasicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">  
    6.         <property name="authenticationManager">  
    7.             <ref bean="authenticationManager"/>  
    8.         </property>  
    9.         <property name="authenticationEntryPoint">  
    10.             <ref bean="BasicProcessingFilterEntryPoint"/>  
    11.         </property>  
    12.     </bean>  

    即可.
    不過在HTTP基本認證里需要注意的地方是:好多人配置好了怎么看不到效果啊,一開始我也是很郁悶,看了BasicProcessingFilter的源代碼:
    String header = httpRequest.getHeader("Authorization");//我們一般進入網頁測試的時候這里的header始終是null的
    Java代碼 復制代碼
    1. if (logger.isDebugEnabled()) {  
    2.             logger.debug("Authorization header: " + header);  
    3.         }  
    4.         if ((header != null) && header.startsWith("Basic ")) {//從這里可以看到一般的登陸基本認證是不起作用的  
    5. .................  

    只有在服務器上配置哪個目錄在訪問的時候用HTTP基本認證,它才會起作用(一開始還以為是Acegi的BUG呢)
    下面說一下真正對URL資源的保護了filterSecurityInterceptor它的本質是個過濾器,有了前面*管理器的基礎了這就很容易了:
    Java代碼 復制代碼
    1. <bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">  
    2.         <property name="authenticationManager">  
    3.             <ref local="authenticationManager"/>  
    4.         </property>  
    5.         <property name="accessDecisionManager">  
    6.             <ref local="accessDecisionManager"/>  
    7.         </property>  
    8.         <property name="objectDefinitionSource"><!-- 把URL和可訪問的用戶組對應起來 -->  
    9.             <value>  
    10.                 CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<!-- 把URL全部轉化為小寫 -->  
    11.                 PATTERN_TYPE_APACHE_ANT<!-- 以ANT的形式來配置路徑 -->  
    12.                 /ok.html=ROLE_USER  
    13.             </value>  
    14.         </property>  
    15.     </bean>  

    光這樣配置還是不夠的,因為當授權失敗的時候會拋出異常的,我們應該配置一個異常過濾器來捕獲它,exceptionTranslationFilter它是用來捕獲異常的,看一下配置吧:
    Java代碼 復制代碼
    1. <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">  
    2.       <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>  
    3.       <property name="accessDeniedHandler">  
    4.         <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">  
    5.             <property name="errorPage" value="/failure.html"/><!-- 發生異常轉向的網頁 -->  
    6.         </bean>  
    7.       </property>  
    8.    </bean>  
    9.    <bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">  
    10.         <property name="loginFormUrl"><value>/Login.html</value></property><!-- 得到表單的信息 -->  
    11.         <property name="forceHttps"><value>false</value></property><!-- 不用https -->  
    12.    </bean>  

    這樣就OK了
    最后說一下對類中方法的保護:
    首先寫一個類并在spring中配置好:
    Java代碼 復制代碼
    1. package org.li.acegi;  
    2.   
    3. public class TestAcegi  
    4. {  
    5.     public void Role()  
    6.     {  
    7.         System.out.println("javafish");  
    8.     }  
    9. }  
    10. <bean id="testAcegi" class="org.li.acegi.TestAcegi"/>  

    然看寫個servlet訪問一下它
    Java代碼 復制代碼
    1. package org.li.servlet;  
    2.   
    3. import java.io.IOException;  
    4. import java.io.PrintWriter;  
    5.   
    6. import javax.servlet.ServletException;  
    7. import javax.servlet.http.HttpServlet;  
    8. import javax.servlet.http.HttpServletRequest;  
    9. import javax.servlet.http.HttpServletResponse;  
    10.   
    11. import org.li.acegi.TestAcegi;  
    12. import org.springframework.context.ApplicationContext;  
    13. import org.springframework.web.context.support.WebApplicationContextUtils;  
    14.   
    15. public class TestServlet extends HttpServlet  
    16. {  
    17.     private static final long serialVersionUID = -5610016980827214773L;  
    18.   
    19.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
    20.             throws ServletException, IOException  
    21.     {  
    22.         response.setContentType("text/html;charset=GBK");  
    23.         PrintWriter out = response.getWriter();  
    24.         ApplicationContext ctx =   
    25.             WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());  
    26.         TestAcegi test = (TestAcegi)ctx.getBean("testAcegi");  
    27.         test.Role();//訪問TestAcegi類的Role方法  
    28.         out.println("調用成功");  
    29.     }  
    30.   
    31.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
    32.             throws ServletException, IOException  
    33.     {  
    34.         doGet(request,response);  
    35.     }  
    36.   
    37. }  

    準備工作做好了,開始配置Acegi
    先在Spring里給Acegi做個代理:
    Java代碼 復制代碼
    1. <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
    2.         <property name="beanNames">  
    3.             <list>  
    4.                 <value>testAcegi</value><!-- 要代理的Bean的id -->  
    5.             </list>  
    6.         </property>  
    7.         <property name="interceptorNames">  
    8.             <list>  
    9.                 <value>methodSecurityInterceptor</value><!-- 代理為... -->  
    10.             </list>  
    11.         </property>  
    12.     </bean>  

    里面的methodSecurityInterceptor呢配置為:
    Java代碼 復制代碼
    1. <bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">  
    2.         <property name="authenticationManager">  
    3.             <ref bean="authenticationManager"/>  
    4.         </property>  
    5.         <property name="accessDecisionManager">  
    6.             <ref bean="accessDecisionManager"/>  
    7.         </property>  
    8.         <property name="objectDefinitionSource"><!-- 對代理的類的方法開始配置權限 -->  
    9.             <value>org.li.acegi.TestAcegi.Role=ROLE_USER</value>  
    10.         </property>  
    11.     </bean>  

    這樣當直接訪問http://localhost:8080/AcegiWeb/servlet/TestServlet的時候會發現不可訪問,控件臺也不輸出”javafish”,當輸入正確的用戶名和密碼之后便可以訪問.
    這樣它就對類的方法調用起了保護的作用,這一點可以把Acegi應用到DWR上效果是很理想的.
    對于Acegi有很多的過濾器不用全寫在web.xml里,acegi提供了一個特殊的過濾器我們可以寫成這樣,在Web.xml里:
    Java代碼 復制代碼
    1. <filter>  
    2.         <filter-name>Acegi</filter-name>  
    3.         <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>  
    4.         <init-param>  
    5.             <param-name>targetClass</param-name>  
    6.             <param-value>org.acegisecurity.util.FilterChainProxy</param-value>  
    7.         </init-param>  
    8.     </filter>  
    9.     <filter-mapping>  
    10.         <filter-name>Acegi</filter-name>  
    11.         <url-pattern>/*</url-pattern>  
    12.     </filter-mapping>  
    13.     <context-param>  
    14.         <param-name>contextConfigLocation</param-name>  
    15.         <param-value>  
    16.             /WEB-INF/applicationContext.xml  
    17.         </param-value>  
    18.     </context-param>  
    19.     <listener>  
    20.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    21.     </listener>  
    22.       
    23.     <listener>  
    24.         <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
    25.     </listener>  
    26.     <listener>  
    27.         <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>  
    28.     </listener>  
    29.   <servlet>  
    30.     <servlet-name>TestServlet</servlet-name>  
    31.     <servlet-class>org.li.servlet.TestServlet</servlet-class>  
    32.   </servlet>  
    33.   
    34.   <servlet-mapping>  
    35.     <servlet-name>TestServlet</servlet-name>  
    36.     <url-pattern>/servlet/TestServlet</url-pattern>  
    37.   </servlet-mapping>  

    在Spring的配置文件里:
    Java代碼 復制代碼
    1. <bean id="chainProxy" class="org.acegisecurity.util.FilterChainProxy">  
    2.         <property name="filterInvocationDefinitionSource">  
    3.             <value>  
    4.                 CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON  
    5.             PATTERN_TYPE_APACHE_ANT  
    6.             /**=HttpSessionContextIntegrationFilter,authenticationProcessingFilter,BasicProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor  
    7.             </value>  
    8.         </property>  
    9.     </bean>  

    posted on 2008-08-01 11:21 找個美女做老婆 閱讀(225) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    公告

    本blog已經搬到新家了, 新家:www.javaly.cn
     http://www.javaly.cn

    常用鏈接

    留言簿(6)

    隨筆檔案

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲一二成人精品区| 亚洲日韩一区二区一无码| 波多野结衣在线免费观看| 亚洲av无码成人精品国产| 国外亚洲成AV人片在线观看| 一区二区在线免费观看| 亚洲熟女www一区二区三区| 国产亚洲?V无码?V男人的天堂 | 在线观看国产一区亚洲bd| 亚洲乱码国产一区三区| 免费做爰猛烈吃奶摸视频在线观看| 麻豆91免费视频| 666精品国产精品亚洲| 免费永久看黄在线观看app| 少妇人妻偷人精品免费视频| 亚洲欧美不卡高清在线| 亚洲精品色午夜无码专区日韩| 在线观看av永久免费| 成人无码视频97免费| 亚洲成av人无码亚洲成av人| 亚洲国产第一页www| 日本黄页网站免费| 久久ww精品w免费人成| 永久免费无码日韩视频| 亚洲免费网站在线观看| 亚洲综合图色40p| 日韩精品视频免费在线观看| 在线观看免费av网站| 久久www免费人成精品香蕉| 亚洲日韩亚洲另类激情文学| 亚洲午夜未满十八勿入| 国产亚洲情侣一区二区无| 韩国欧洲一级毛片免费| h视频在线观看免费完整版| 丝瓜app免费下载网址进入ios| 亚洲高清国产拍精品熟女| 亚洲成年人电影在线观看| 亚洲高清国产AV拍精品青青草原| 免费国产成人高清在线观看麻豆| 麻豆最新国产剧情AV原创免费 | 丰满人妻一区二区三区免费视频|