Acegi-security-samples-tutorial-1.0.7.zip 实例代码解析

前面一篇文章,展现了Acegi的作用:

现在我将对其中的代码进行讲解:

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>

<web-app>

    <display-name>Acegi Security Tutorial Application</display-name>
   
 <!--
   - Location of the XML file that defines the root application context
   - Applied by ContextLoaderListener.
   -->
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/applicationContext-acegi-security.xml
  </param-value>
 </context-param>
 <!--
   FilterToBeanProxy是一个特殊的Servlet过滤器,它本身做的事并不多,
   而是将自己的工作委托给Spring应用上下文中的另一个Bean来完成。
   被委托的Bean和其他的Servlet过滤器一样,实现了javax.servlet.Filter接口,
   但它是通过Spring配置文件而不是web.xml配置的。
  -->
    <filter>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
        <init-param>
            <param-name>targetClass</param-name>
            <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
        </init-param>
    </filter>

    <filter-mapping>
      <filter-name>Acegi Filter Chain Proxy</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
 
 <!--
   - Loads the root application context of this web app at startup.
   - The application context is then available via
   - WebApplicationContextUtils.getWebApplicationContext(servletContext).
    -->
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

  <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>

</web-app>


users.properties文件:

#配置用户信息
#超级用户
marissa=koala,ROLE_SUPERVISOR
#普通用户
dianne=emu,ROLE_USER
scott=wombat,ROLE_USER
#禁止用户
peter=opal,disabled,ROLE_USER

 

applicationContext-acegi-security.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!-- 一个简单的Acegi配置 -->
<beans>
    <!-- Acegi的过滤器链 -->
 <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
  <property name="filterInvocationDefinitionSource">
   <value><![CDATA[
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
   ]]></value>
  </property>
 </bean>

    <!-- 设置一个安全上下文。其中HttpSessionIntegrationFilter适用于大多数情形。它将Authentication对象保存在HTTP会话中,使之能够跨越多个请求。
     -->
 <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>

 <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
  <constructor-arg value="/index.jsp"/> <!-- URL redirected to after logout -->
  <constructor-arg>
   <list>
    <ref bean="rememberMeServices"/>
    <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
   </list>
  </constructor-arg>
 </bean>

    <!-- AuthenticationProcessingFilter是处理基于表单身份验证的过滤器。
         authenticationFailureUrl指定当身份验证失败时
         defaultTargetUrl定义了当出现目标URL不在HTTP会话中的异常情况时将发生什么。
        这可能发生在用户通过浏览器书签或其他方式而不是通过SecurityEnforcementFilter到达登录页面的情况下。
         filterProcessesUrl告诉AuthenticationProcessingFilter应该拦截哪个URL。
        这个URL与登录表单中action属性的值一样。它的默认值为/j_acegi_security_check,
        但我们在这里显式定义了该值,用于说明你可以根据需要改变这个值。
     -->
 <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>
  <property name="defaultTargetUrl" value="/"/>
  <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
  <property name="rememberMeServices" ref="rememberMeServices"/>
 </bean>

 <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>

 <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="rememberMeServices" ref="rememberMeServices"/>
 </bean>

 <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
  <property name="key" value="changeThis"/>
  <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
 </bean>

    <!-- 访问出现异常时的处理 -->
 <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
  <!--AuthenticationProcessingFilterEntryPoint是一个提供给用户基于HTML的登录表单的认证入口点。  -->
  <property name="authenticationEntryPoint">
     <!-- 属性loginFromUrl配置了一个登录表单的URL。当需要用户登录时,
          AuthenticationProcessingFilterEntryPoint会将用户重定向到该URL。
      -->
   <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
    <property name="loginFormUrl" value="/acegilogin.jsp"/>
    <property name="forceHttps" value="false"/>
   </bean>
  </property>
  <!-- 访问权限禁止处理 -->
  <property name="accessDeniedHandler">
   <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
    <property name="errorPage" value="/accessDenied.jsp"/>
   </bean>
  </property>
 </bean>

    <!-- FilterSecurityInterceptor类负责执行安全拦截器的工作 -->
 <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
  <!-- 认证管理器Bean的引用 -->
  <property name="authenticationManager" ref="authenticationManager"/>
  <!-- 访问决策(即授权)管理器Bean的引用 -->
  <property name="accessDecisionManager">
       <!-- Acegi的访问决策管理器如何计票
                访问决策管理器           如 何 决 策
              AffirmativeBased     当至少有一个投票者投允许访问票时允许访问
              ConsensusBased       当所有投票者都投允许访问票时允许访问
              UnanimousBased       当没有投票者投拒绝访问票时允许访问
        -->
   <bean class="org.acegisecurity.vote.AffirmativeBased">
        <!--默认地,当全部投票者都投弃权票时,所有的访问决策管理者都将拒绝访问资源。
            你可以配合为true,即建立了一个“沉默即同意”的策略。换句话说,如果所有的投票者都放弃投票,
            则如同它们都投赞成票一样,访问被授权。
          -->
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
        <!-- decisionVoters属性为访问决策管理器提供一组投票者 -->
     <list>
         <!-- RoleVoter只在受保护资源有以ROLE_为前缀的配置属性才进行投票。然而,ROLE_前缀只是默认值。你可以选择通过设置rolePrefix属性来重载这个默认前缀:
                              <bean id="roleVoter"
                                     class="net.sf.acegisecurity.vote.RoleVoter">
                                <property name="rolePrefix">
                                        <value>GROUP_</value>
                                </property>
                              </bean>
                                 在这里,默认的前缀被重载为GROUP_。
          -->
      <bean class="org.acegisecurity.vote.RoleVoter"/>
      <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
     </list>
    </property>
   </bean>
  </property>
  <!-- 属性objectDefinitionSource告诉安全拦截器被拦截的各种请求所需要的授权是什么.
        第一行是一个指令,表明在比较请求的URL在和紧跟其后定义的模式之前必须首先正规化为小写字母。
        该属性的其余几行将URL模式映射为允许用户访问这些URL时必须授予用户的权限。
       PATTERN_TYPE_APACHE_ANT指令则URL模式可以采用类似与ANT,或不添加该指令,URL模式以正则表达式的形式描述,如:
       <property name="objectDefinitionSource">
                <value>
          CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          /A/admin/.*/Z=ROLE_ADMIN
          /A/student/.*/Z=ROLE_STUDENT,ROLE_ALUMNI
          /A/instruct/.*/Z=ROLE_INSTRUCTOR
        </value>
      </property>
  -->
  <property name="objectDefinitionSource">
   <value><![CDATA[
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /secure/extreme/**=ROLE_SUPERVISOR
    /secure/**=IS_AUTHENTICATED_REMEMBERED
    /**=IS_AUTHENTICATED_ANONYMOUSLY
   ]]></value>
  </property>
 </bean>

 <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
  <property name="userDetailsService" ref="userDetailsService"/>
  <property name="key" value="changeThis"/>
 </bean>

   <!-- 认证管理器负责确定用户身份的
        ProviderManager是认证管理器的一个实现,它将验证身份的责任委托给一个或多个认证提供者.
        ProviderManager的思路是使你能够根据多个身份管理源来认证用户。
         它不是依靠自己实现身份验证,而是逐一遍历一个认证提供者的集合,直到某一个认证提供者能够成功地验证该用户的身份
         (或者已经尝试完了该集合中所有的认证提供者)。
   -->
 <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
  <property name="providers">
   <list>
       <!-- 从数据库中获取用户信息,包括用户名和密码。-->
    <ref local="daoAuthenticationProvider"/>
    <!-- 匿名用户 -->
    <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
     <property name="key" value="changeThis"/>
    </bean>
    <!-- 已有登录记录的用户 -->
    <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
     <property name="key" value="changeThis"/>
    </bean>
   </list>
  </property>
 </bean>

    <!--一个DaoAuthenticationProvider是一个简单的认证提供者,它使用DAO来从数据库中获取用户信息(包括用户的密码)。  -->
 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="userDetailsService" ref="userDetailsService"/>
 </bean>

 <!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
 <!-- Acegi提供了两个可供选择的AuthenticationDao的实例:InMemoryDaoImpl和JdbcDaoImpl。在此实例中为了方便起见,采用使用内存DAO即InMemoryDaoImpl-->
 <bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
  <property name="userProperties">
   <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="location" value="/WEB-INF/users.properties"/>
   </bean>
  </property>
 </bean>

 <!-- This bean is optional; it isn't used by any other bean as it only listens and logs 日志监听-->
 <bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>

</beans>

 

JSP页面的代码:

index.jsp:

      <html>
<body>
<h1>主页</h1>
任何人可浏览此页面。

<p><a href="secure/index.jsp">安全页面</a>
<p><a href="secure/extreme/index.jsp">超级安全页面</a>
</body>
</html>

acegilogin.jsp:

<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
<%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %>
<%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %>
<%@ page import="org.acegisecurity.AuthenticationException" %>

<html>
  <head>
    <title>登录</title>
    <style type="text/css">
    *{
    font-size:12px
    }
    </style>
  </head>

  <body>
    <h1>登录</h1>

 <P>有效用户:
 <P>
 <P>用户名:<b>marissa</b>, 密码: <b>koala</b> (超级用户)
 <P>用户名:<b>dianne</b>, 密码: <b>emu</b> (普通用户)
 <p>用户名:<b>scott</b>, 密码: <b>wombat</b> (普通用户)
 <p>用户名:<b>peter</b>, 密码: <b>opal</b> (禁止用户)
 <p>
 
    <%-- 当输入用户名或密码错误时显示提示信息--%>
    <c:if test="${not empty param.login_error}">
      <font color="red">
        抱歉,您登录失败,请重新登录!<BR><BR>
        原因: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
      </font>
    </c:if>

    <form action="<c:url value='j_acegi_security_check'/>" method="POST">
      <table>
        <tr><td>用户名:</td><td><input type='text' name='j_username' <c:if test="${not empty param.login_error}">value='<c:out value="${ACEGI_SECURITY_LAST_USERNAME}"/>'</c:if>></td></tr>
        <tr><td>密码:</td><td><input type='password' name='j_password'></td></tr>
        <tr><td><input type="checkbox" name="_acegi_security_remember_me"></td><td>2周内不用再登录</td></tr>

        <tr><td colspan='2'><input name="submit" type="submit" value="提交"><input name="reset" type="reset"></td></tr>
      </table>

    </form>

  </body>
</html>
accessDenied.jsp:

<%@ page import="org.acegisecurity.context.SecurityContextHolder" %>
<%@ page import="org.acegisecurity.Authentication" %>
<%@ page import="org.acegisecurity.ui.AccessDeniedHandlerImpl" %>

<h1>对不起,您无权访问!</h1>


<p>
<%= request.getAttribute(AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY)%>

<p>

<%  Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  if (auth != null) { %>
   Authentication object as a String: <%= auth.toString() %><BR><BR>
<%      } %>

secure/index.jsp:

   <html>
<body>
<h1>安全页面</h1>
这是一个受保护的页面,当您的登录信息已经被记住或您在本次会话中已认证通过。
<p><a href="../">主页</a>
<p><a href="../j_acegi_logout">退出</a>
</body>
</html>

secure/extreme/index.jsp:

<html>
<body>
<h1>非常安全页面</h1>
这是一个保护页面,只有当你是超级用户才可以浏览此页面。

<p><a href="../../">主页</a>
<p><a href="../../j_acegi_logout">退出</a>
</body>
</html>

下载源代码地址: http://d.download.csdn.net/down/648973/foamflower

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值