学习Acegi-认证(authentication)

最近两星期在学习acegi,过程中感谢 JavaEyeSpringSide和在网上提供acegi学习心得的网友们。
为了加深自己的认识,准备写下一些DEMO,希望可以给准备学习acegi的同学一些帮助。
作为安全服务离不开认证和授权这两个主要组成部分。而这篇文章就是针对acegi的认证服务。
《学习Acegi-认证(authentication)》
代码环境基于:
JDK1.5
acegi1.0.3
spring2.0

IDE基于:
Eclipse3.2+MyEclipse5.0.1

面向人员:
熟悉Eclipse+MyEclipse开发但刚开始了解acegi的人员。如果你是高手请指出文章不足之处。

1.建立一个MyEclipse的WebProject,把下列jar文件拷贝到项目的WEB-INF/lib目录:
acegi-security-1.0.3.jar
spring2.0.jar
commons-codec-1.3.jar
费话说一句(占些字数):这是因为代码运行需要这些包的支持。

2.修改WEB-INF下的web.xml文件,内容如下:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <web-app>   
  3.   
  4.     <display-name>acegi Example of liuyxit</display-name>   
  5.        
  6.     <!--   
  7.         定义应用的上下文参数,用于ContextLoaderListener       
  8.     -->   
  9.     <context-param>   
  10.         <param-name>contextConfigLocation</param-name>   
  11.         <param-value>   
  12.             classpath:spring/applicationContext.xml   
  13.         </param-value>   
  14.     </context-param>   
  15.   
  16.     <!--acegi 的filter链代理-->   
  17.     <filter>   
  18.         <filter-name>Acegi Filter Chain Proxy</filter-name>   
  19.         <filter-class>   
  20.             org.acegisecurity.util.FilterToBeanProxy   
  21.         </filter-class>   
  22.         <init-param>   
  23.             <param-name>targetClass</param-name>   
  24.             <param-value>   
  25.                 org.acegisecurity.util.FilterChainProxy   
  26.             </param-value>   
  27.         </init-param>   
  28.     </filter>   
  29.     <filter-mapping>   
  30.         <filter-name>Acegi Filter Chain Proxy</filter-name>   
  31.         <url-pattern>/*</url-pattern>   
  32.     </filter-mapping>   
  33.        
  34.     <!--   
  35.         装载应用软件的Spring上下文   
  36.         要由WebapplicationContextUtils.getWebApplicationnContext(servletContext)得到.   
  37.     -->   
  38.     <listener>   
  39.         <listener-class>   
  40.             org.springframework.web.context.ContextLoaderListener   
  41.         </listener-class>   
  42.     </listener>   
  43. </web-app>  
<?xml version="1.0" encoding="UTF-8"?>
<web-app>

	<display-name>acegi Example of liuyxit</display-name>
	
	<!--
		定义应用的上下文参数,用于ContextLoaderListener	  
	-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:spring/applicationContext.xml
		</param-value>
	</context-param>

	<!--acegi 的filter链代理-->
	<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>
	
	<!--
		装载应用软件的Spring上下文
		要由WebapplicationContextUtils.getWebApplicationnContext(servletContext)得到.
	-->
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
</web-app>


其中FilterChainProxy实现了filter接口,它主要是实例化FilterChainProxy,并把所有动作交由FilterChainProxy处理。这样简化了web.xml的配置,并且充分利用了Spring IOC管理Bean的优势。

3.在src目录右键新建一个resource folder,在下面再建立acegi和spring目录
在spring目录中创建applicationContext.xml文件,内容:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:aop="http://www.springframework.org/schema/aop"  
  5.        xmlns:tx="http://www.springframework.org/schema/tx"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd   
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"   
  9.            default-autowire="byName" default-lazy-init="true">   
  10.        
  11.      <!--   ========================  FILTER CHAIN  =======================   -->    
  12.      <bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy">    
  13.        <property name="filterInvocationDefinitionSource">    
  14.           <value>    
  15.             CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON   
  16.             PATTERN_TYPE_APACHE_ANT   
  17.             /**=authenticationProcessingFilter,exceptionTranslationFilter   
  18.          </value>   
  19.       </property>   
  20.     </bean>      
  21.     <!-- ======================== 认证filter ======================= -->   
  22.       
  23.     <!-- 表单认证处理filter -->   
  24.     <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">   
  25.         <property name="authenticationManager" ref="authenticationManager"/>   
  26.         <property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>   
  27.         <property name="defaultTargetUrl" value="/userinfo.jsp"/>   
  28.         <property name="filterProcessesUrl" value="/j_acegi_security_check"/>   
  29.     </bean>       
  30.           
  31.    <!-- 认证管理器 -->   
  32.    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">   
  33.       <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->   
  34.          <list>   
  35.             <ref local="daoAuthenticationProvider"/>   
  36.          </list>   
  37.       </property>   
  38.    </bean>      
  39.     <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">   
  40.         <property name="userDetailsService" ref="inMemoryDaoImpl"/>           
  41.     </bean>       
  42.     <!-- 用户资料-->   
  43.      <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">     
  44.         <property name="userMap">     
  45.             <value>     
  46.                 liuyxit=123,ROLE_SUPERVISOR   
  47.                 user1=user1,ROLE_USER   
  48.                 user2=user2,disabled,ROLE_USER      
  49.             </value>     
  50.         </property>     
  51.     </bean>   
  52.     <!-- 异常处理filter -->   
  53.     <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">   
  54.         <property name="authenticationEntryPoint">   
  55.             <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">   
  56.                 <property name="loginFormUrl" value="/acegilogin.jsp"/>   
  57.                 <property name="forceHttps" value="false"/>   
  58.             </bean>   
  59.         </property>   
  60.         <property name="accessDeniedHandler">   
  61.             <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">   
  62.                 <property name="errorPage" value="/accessDenied.jsp"/>   
  63.             </bean>   
  64.         </property>   
  65.     </bean>       
  66. </beans>   
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
           default-autowire="byName" default-lazy-init="true">
    
     <!--   ========================  FILTER CHAIN  =======================   --> 
     <bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy"> 
       <property name="filterInvocationDefinitionSource"> 
          <value> 
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /**=authenticationProcessingFilter,exceptionTranslationFilter
         </value>
      </property>
    </bean>   
    <!-- ======================== 认证filter ======================= -->
   
    <!-- 表单认证处理filter -->
    <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="/userinfo.jsp"/>
        <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
    </bean>    
       
   <!-- 认证管理器 -->
   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->
         <list>
            <ref local="daoAuthenticationProvider"/>
         </list>
      </property>
   </bean>   
    <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="inMemoryDaoImpl"/>        
    </bean>    
    <!-- 用户资料-->
     <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">  
        <property name="userMap">  
            <value>  
                liuyxit=123,ROLE_SUPERVISOR
                user1=user1,ROLE_USER
                user2=user2,disabled,ROLE_USER   
            </value>  
        </property>  
    </bean>
    <!-- 异常处理filter -->
    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <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>    
</beans> 


[list=A]其中filterChainProxy就是由web.xml声明的filter(FilterToBeanProxy)的targetClass。它主要是装载filterInvocationDefinitionSource指定的filter类(例子中为authenticationProcessingFilter,exceptionTranslationFilter),并顺序调用它们的doFilter方法,进行安全服务处理。[/list]
[list=B]而authenticationProcessingFilter是处理一个认证表单,登陆用的表单必须提交用户名和密码这两个参数给这个filter.由用户名和密码构造一个UsernamePasswordAuthenticationToken,将传给AuthenticationManager的authenticate方法进行认证处理。该filter默认处理filterProcessesUrl属性指定的URL,认证失败会转到authenticationFailureUrl,认证成功会转到defaultTargetUrl页面。[/list]
[list=C]AuthenticationManager顾名思义认证管理器,它只有一个接口方法authenticate用于返回认证结果,他的实现类由多个AuthenticationProvider进行投票,决定认证是否通过。[/list]
[list=D]daoAuthenticationProvider是检验用户录入的认证数据是否正确(说白了就是用户名和密码是否正确)[/list]
[list=E]inMemoryDaoImpl是给daoAuthenticationProvider提供系统的用户资料。而资料的来源是从配置中装载到内存的。[/list]
[list=F]当认证不通过时,AuthenticationManager的实现类AbstractAuthenticationManager会抛出AuthenticationException类型的异常。这时排在最后的exceptionTranslationFilter会捕获该异常,并转向authenticationEntryPoint。[/list]

4.在WebRoot下创建index.jsp(其实不要也没关系,主要是为了方便),直接转向用户资料显示页。内容如下:
Java代码 复制代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>   
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">   
  3. <html>   
  4. <head>   
  5.     <META HTTP-EQUIV="Refresh" CONTENT="0;URL=userinfo.jsp">   
  6. </head>   
  7.   
  8. <body>   
  9. <p>Loading ...</p>   
  10. </body>   
  11. </html>  
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=userinfo.jsp">
</head>

<body>
<p>Loading ...</p>
</body>
</html>


5.在WebRoot下创建userinfo.jsp,用于显示当前登陆的用户信息。内容如下
Java代码 复制代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>   
  2. <%@ page import="org.acegisecurity.context.SecurityContextHolder"%>   
  3. <%@ page import="org.acegisecurity.userdetails.*"%>   
  4.   
  5. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">   
  6. <html>   
  7.     <head>   
  8.         <title>My JSP 'pass.jsp' starting page</title>   
  9.   
  10.         <meta http-equiv="pragma" content="no-cache">   
  11.         <meta http-equiv="cache-control" content="no-cache">   
  12.         <meta http-equiv="expires" content="0">   
  13.         <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">   
  14.         <meta http-equiv="description" content="This is my page">   
  15.     </head>   
  16.   
  17.     <body>   
  18.         当前用户:   
  19.         <%   
  20.             Object obj = SecurityContextHolder.getContext().getAuthentication();           
  21.             if (null != obj){   
  22.                 Object userDetail = SecurityContextHolder.getContext().getAuthentication().getPrincipal();   
  23.                 String username = "";   
  24.                 if (userDetail instanceof UserDetails) {   
  25.                     username = ((UserDetails) userDetail).getUsername();   
  26.                 } else {   
  27.                     username = userDetail.toString();   
  28.                 }   
  29.                 out.print(username);   
  30.                 out.print("<br><a href=/"j_acegi_logout/">注销</a>");   
  31.             }else{   
  32.                 out.print("当前没有有效的用户");   
  33.                 out.print("<br><a href=/"acegilogin.jsp/">登陆</a>");   
  34.             }   
  35.         %>          
  36.     </body>   
  37. </html>  
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="org.acegisecurity.context.SecurityContextHolder"%>
<%@ page import="org.acegisecurity.userdetails.*"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<title>My JSP 'pass.jsp' starting page</title>

		<meta http-equiv="pragma" content="no-cache">
		<meta http-equiv="cache-control" content="no-cache">
		<meta http-equiv="expires" content="0">
		<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
		<meta http-equiv="description" content="This is my page">
	</head>

	<body>
		当前用户:
		<%
			Object obj = SecurityContextHolder.getContext().getAuthentication();		
			if (null != obj){
				Object userDetail = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
				String username = "";
				if (userDetail instanceof UserDetails) {
					username = ((UserDetails) userDetail).getUsername();
				} else {
					username = userDetail.toString();
				}
				out.print(username);
				out.print("<br><a href=/"j_acegi_logout/">注销</a>");
			}else{
				out.print("当前没有有效的用户");
				out.print("<br><a href=/"acegilogin.jsp/">登陆</a>");
			}
		%>		
	</body>
</html>


6.在WebRoot下创建acegilogin.jsp
Java代码 复制代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>   
  2. <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %>   
  3. <%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %>   
  4. <%@ page import="org.acegisecurity.AuthenticationException" %>   
  5. <html>   
  6.   <head>   
  7.     <title>Login</title>   
  8.   </head>   
  9.   <body>   
  10.     <h1>Login</h1>   
  11.   
  12.     <P>Valid users:   
  13.     <P>   
  14.     <P>username <b>liuyxit</b>, password <b>123</b> (supervisor)   
  15.     <P>username <b>user1</b>, password <b>user1</b> (normal user)   
  16.     <p>username <b>user2</b>, password <b>user2</b> (user disabled)   
  17.     <p>   
  18.     <%   
  19.         String strError = request.getParameter("login_error");         
  20.         if (null != strError){    
  21.      %>   
  22.       <font color="red">   
  23.         你的登陆失败,请重试。<BR><BR>   
  24.          原因: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>   
  25.       </font>   
  26.       <%   
  27.         }//end if   
  28.       %>   
  29.   
  30.     <form action="j_acegi_security_check" method="POST">   
  31.       <table>   
  32.         <tr><td>User:</td><td><input type='text' name='j_username' value='<%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY) %>'></td></tr>   
  33.         <tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>   
  34.         <tr><td><input type="checkbox" name="_acegi_security_remember_me"></td><td>2周内自动登录</td></tr>   
  35.   
  36.         <tr><td colspan='2'><input name="submit" type="submit"></td></tr>   
  37.         <tr><td colspan='2'><input name="reset" type="reset"></td></tr>   
  38.       </table>   
  39.     </form>   
  40.   
  41.   </body>   
  42. </html>  
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %>
<%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %>
<%@ page import="org.acegisecurity.AuthenticationException" %>
<html>
  <head>
    <title>Login</title>
  </head>
  <body>
    <h1>Login</h1>

	<P>Valid users:
	<P>
	<P>username <b>liuyxit</b>, password <b>123</b> (supervisor)
	<P>username <b>user1</b>, password <b>user1</b> (normal user)
	<p>username <b>user2</b>, password <b>user2</b> (user disabled)
	<p>
    <%
    	String strError = request.getParameter("login_error");    	
    	if (null != strError){ 
     %>
      <font color="red">
        你的登陆失败,请重试。<BR><BR>
         原因: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
      </font>
      <%
      	}//end if
      %>

    <form action="j_acegi_security_check" method="POST">
      <table>
        <tr><td>User:</td><td><input type='text' name='j_username' value='<%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY) %>'></td></tr>
        <tr><td>Password:</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"></td></tr>
        <tr><td colspan='2'><input name="reset" type="reset"></td></tr>
      </table>
    </form>

  </body>
</html>


7.OK,发布项目,访问http://localhost:8080/acegiexample
这时index.jsp会自动转向userinfo.jsp,由于还没有用户登录,所以没有资料显示。按登陆链接进入登录页,登录成功后会看到显示用户名的页面(当然可以有更多的用户资料,但这仅仅是example),不成功时会在登录页提示信息。我们可以用user1和user2登陆,可以分别测试登录成功和失败的流程。

8.可以看到登录页上有自动登陆功能,而userinfo.jsp页有注销功能。但还是不起作用,好,现在我们马上首手加入这两个功能。看acegi可以方便到什么程度。修改applicationContext.xml如下:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:aop="http://www.springframework.org/schema/aop"  
  5.        xmlns:tx="http://www.springframework.org/schema/tx"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd   
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"   
  9.            default-autowire="byName" default-lazy-init="true">    
  10.        
  11.      <!--   ========================  FILTER CHAIN  =======================   -->    
  12.      <bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy" >    
  13.        <property name="filterInvocationDefinitionSource" >    
  14.           <value >    
  15.             CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON   
  16.             PATTERN_TYPE_APACHE_ANT   
  17.              /** =authenticationProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter   
  18.          </value>   
  19.       </property>   
  20.     </bean>      
  21.     <!-- ======================== 认证filter ======================= -->   
  22.       
  23.     <!-- 表单认证处理filter -->   
  24.     <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">   
  25.         <property name="authenticationManager" ref="authenticationManager"/>   
  26.         <property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>   
  27.         <property name="defaultTargetUrl" value="/userinfo.jsp"/>   
  28.         <property name="filterProcessesUrl" value="/j_acegi_security_check"/>   
  29.     </bean>   
  30.        
  31.     <!-- 利用cookie自动登陆filter -->   
  32.     <bean id="rememberMeProcessingFilter"  
  33.           class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">   
  34.         <property name="authenticationManager"  
  35.                   ref="authenticationManager"/>   
  36.         <property name="rememberMeServices" ref="rememberMeServices"/>   
  37.     </bean>       
  38.     <bean id="rememberMeServices"  
  39.           class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">   
  40.         <property name="userDetailsService" ref="inMemoryDaoImpl"/>   
  41.         <property name="key" value="javargb"/>   
  42.     </bean>     
  43.     <bean id="rememberMeAuthenticationProvider"  
  44.           class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">   
  45.         <property name="key" value="javargb"/>   
  46.     </bean>      
  47.        
  48.     <!-- 注销处理filter -->   
  49.     <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">   
  50.       <constructor-arg value="/acegilogin.jsp"/> <!-- URL redirected to after logout -->   
  51.       <constructor-arg>   
  52.          <list>   
  53.               <ref bean="rememberMeServices"/>   
  54.               <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>   
  55.          </list>   
  56.       </constructor-arg>   
  57.    </bean>   
  58.        
  59.    <!-- 认证管理器 -->   
  60.    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">   
  61.       <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->   
  62.          <list>   
  63.             <ref local="daoAuthenticationProvider"/>   
  64.             <ref local="rememberMeAuthenticationProvider"/>   
  65.          </list>   
  66.       </property>   
  67.    </bean>      
  68.     <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">   
  69.         <property name="userDetailsService" ref="inMemoryDaoImpl"/>           
  70.     </bean>       
  71.     <!--    
  72.     <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">   
  73.         <property name="userProperties">   
  74.             <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">   
  75.                 <property name="location" value="classpath:acegi/users.properties"/>   
  76.             </bean>   
  77.         </property>   
  78.     </bean>   
  79.      -->   
  80.      <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">     
  81.         <property name="userMap">     
  82.             <value>     
  83.                 liuyxit=123,ROLE_SUPERVISOR   
  84.                 user1=user1,ROLE_USER   
  85.                 user2=user2,disabled,ROLE_USER      
  86.             </value>     
  87.         </property>     
  88.     </bean>   
  89.     <!-- 异常处理filter -->   
  90.     <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">   
  91.         <property name="authenticationEntryPoint">   
  92.             <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">   
  93.                 <property name="loginFormUrl" value="/acegilogin.jsp"/>   
  94.                 <property name="forceHttps" value="false"/>   
  95.             </bean>   
  96.         </property>   
  97.         <property name="accessDeniedHandler">   
  98.             <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">   
  99.                 <property name="errorPage" value="/accessDenied.jsp"/>   
  100.             </bean>   
  101.         </property>   
  102.     </bean>       
  103. </beans>   
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
           default-autowire="byName" default-lazy-init="true"> 
    
     <!--   ========================  FILTER CHAIN  =======================   --> 
     <bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy" > 
       <property name="filterInvocationDefinitionSource" > 
          <value > 
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
             /** =authenticationProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter
         </value>
      </property>
    </bean>   
    <!-- ======================== 认证filter ======================= -->
   
    <!-- 表单认证处理filter -->
    <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="/userinfo.jsp"/>
        <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
    </bean>
    
    <!-- 利用cookie自动登陆filter -->
    <bean id="rememberMeProcessingFilter"
          class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
        <property name="authenticationManager"
                  ref="authenticationManager"/>
        <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>    
    <bean id="rememberMeServices"
          class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="inMemoryDaoImpl"/>
        <property name="key" value="javargb"/>
    </bean>  
    <bean id="rememberMeAuthenticationProvider"
          class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
        <property name="key" value="javargb"/>
    </bean>   
    
    <!-- 注销处理filter -->
    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/acegilogin.jsp"/> <!-- URL redirected to after logout -->
      <constructor-arg>
         <list>
              <ref bean="rememberMeServices"/>
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
         </list>
      </constructor-arg>
   </bean>
    
   <!-- 认证管理器 -->
   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->
         <list>
            <ref local="daoAuthenticationProvider"/>
            <ref local="rememberMeAuthenticationProvider"/>
         </list>
      </property>
   </bean>   
    <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="inMemoryDaoImpl"/>        
    </bean>    
    <!-- 
    <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
        <property name="userProperties">
            <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                <property name="location" value="classpath:acegi/users.properties"/>
            </bean>
        </property>
    </bean>
     -->
     <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">  
        <property name="userMap">  
            <value>  
                liuyxit=123,ROLE_SUPERVISOR
                user1=user1,ROLE_USER
                user2=user2,disabled,ROLE_USER   
            </value>  
        </property>  
    </bean>
    <!-- 异常处理filter -->
    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <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>    
</beans> 


另要注意:Acegi默认的自动登陆设定参数名为_acegi_security_remember_me,注销链接为/j_acegi_logout。
马上重启Tomcat测试看看^_^。

9.通常用户资料会放在数据库中,而不会放在配置文件,接着下面我们来再行修改一下。
首先创建要用到的用户表和权限表,并插入初始化数据:
Java代码 复制代码
  1. CREATE TABLE USERS(   
  2. USERNAME VARCHAR( 50 ) NOT NULL PRIMARY KEY,   
  3. PASSWORD VARCHAR( 50 ) NOT NULL,   
  4. ENABLED BIT NOT NULL)   
  5.   
  6. INSERT INTO USERS(username,password,enabled) values( ' liuyxit ' , ' 123 ' , ' 1 ' )   
  7. INSERT INTO USERS(username,password,enabled) values( ' user1 ' , ' user1 ' , ' 1 ' )   
  8. INSERT INTO USERS(username,password,enabled) values( ' user2 ' , ' user2 ' , ' 0 ' )   
  9.   
  10. CREATE TABLE AUTHORITIES(   
  11. USERNAME VARCHAR( 50 ) NOT NULL,   
  12. AUTHORITY VARCHAR( 50 ) NOT NULL,   
  13. CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME)   
  14. );   
  15.   
  16. INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' liuyxit ' , ' ROLE_SUPERVISOR ' )   
  17. INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' user1 ' , ' ROLE_USER ' )   
  18. INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' user2 ' , ' ROLE_USER ' )   
CREATE TABLE USERS(
USERNAME VARCHAR( 50 ) NOT NULL PRIMARY KEY,
PASSWORD VARCHAR( 50 ) NOT NULL,
ENABLED BIT NOT NULL)

INSERT INTO USERS(username,password,enabled) values( ' liuyxit ' , ' 123 ' , ' 1 ' )
INSERT INTO USERS(username,password,enabled) values( ' user1 ' , ' user1 ' , ' 1 ' )
INSERT INTO USERS(username,password,enabled) values( ' user2 ' , ' user2 ' , ' 0 ' )

CREATE TABLE AUTHORITIES(
USERNAME VARCHAR( 50 ) NOT NULL,
AUTHORITY VARCHAR( 50 ) NOT NULL,
CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME)
);

INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' liuyxit ' , ' ROLE_SUPERVISOR ' )
INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' user1 ' , ' ROLE_USER ' )
INSERT INTO AUTHORITIES(USERNAME,AUTHORITY) values( ' user2 ' , ' ROLE_USER ' ) 


这里我用的是acegi默认的数据结构,可以改只要你指定JdbcDaoImpl的authoritiesByUsernameQuery和usersByUsernameQuery属性就可以了。另AUTHORITIES表也要一同加入,原因acegi获得userDetail时,也会读取这个表的内容,否则会抛“nested exception is java.sql.SQLException: 对象名 'authorities' 无效”这个异常。

修改applicationContext.xml,变成如下:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:aop="http://www.springframework.org/schema/aop"  
  5.        xmlns:tx="http://www.springframework.org/schema/tx"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd   
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"   
  9.            default-autowire="byName" default-lazy-init="true">   
  10.        
  11.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  12.         <property name="driverClassName">   
  13.             <!-- 请自行修改为对应你的数据库的驱动类 -->   
  14.             <value>net.sourceforge.jtds.jdbc.Driver</value>               
  15.         </property>   
  16.         <property name="url">   
  17.             <!-- 请自行修改为对应你的数据库URL -->   
  18.             <value>jdbc:jtds:sqlserver://localhost:1433/javauser</value>   
  19.         </property>   
  20.         <property name="username">   
  21.             <value>sa</value>   
  22.         </property>   
  23.         <property name="password">   
  24.             <value>javauser</value>   
  25.         </property>   
  26.     </bean>   
  27.      
  28.     <!-- ======================== FILTER CHAIN ======================= -->   
  29.     <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">   
  30.       <property name="filterInvocationDefinitionSource">   
  31.          <value>   
  32.             CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON   
  33.             PATTERN_TYPE_APACHE_ANT   
  34.             /**=authenticationProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter   
  35.          </value>   
  36.       </property>   
  37.     </bean>      
  38.     <!-- ======================== 认证filter ======================= -->   
  39.       
  40.     <!-- 表单认证处理filter -->   
  41.     <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">   
  42.         <property name="authenticationManager" ref="authenticationManager"/>   
  43.         <property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>   
  44.         <property name="defaultTargetUrl" value="/userinfo.jsp"/>   
  45.         <property name="filterProcessesUrl" value="/j_acegi_security_check"/>   
  46.     </bean>   
  47.        
  48.     <!-- 利用cookie自动登陆filter -->   
  49.     <bean id="rememberMeProcessingFilter"  
  50.           class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">   
  51.         <property name="authenticationManager"  
  52.                   ref="authenticationManager"/>   
  53.         <property name="rememberMeServices" ref="rememberMeServices"/>   
  54.     </bean>       
  55.     <bean id="rememberMeServices"  
  56.           class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">   
  57.         <property name="userDetailsService" ref="jdbcDaoImpl"/>   
  58.         <property name="key" value="javargb"/>   
  59.     </bean>     
  60.     <bean id="rememberMeAuthenticationProvider"  
  61.           class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">   
  62.         <property name="key" value="javargb"/>   
  63.     </bean>      
  64.        
  65.     <!-- 注销处理filter -->   
  66.     <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">   
  67.       <constructor-arg value="/acegilogin.jsp"/> <!-- URL redirected to after logout -->   
  68.       <constructor-arg>   
  69.          <list>   
  70.               <ref bean="rememberMeServices"/>   
  71.               <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>   
  72.          </list>   
  73.       </constructor-arg>   
  74.    </bean>   
  75.        
  76.    <!-- 认证管理器 -->   
  77.    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">   
  78.       <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->   
  79.          <list>   
  80.             <ref local="daoAuthenticationProvider"/>   
  81.             <ref local="rememberMeAuthenticationProvider"/>   
  82.          </list>   
  83.       </property>   
  84.    </bean>      
  85.     <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">   
  86.         <property name="userDetailsService" ref="jdbcDaoImpl"/>          
  87.     </bean>       
  88.        
  89.     <bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">   
  90.         <property name="dataSource"><ref bean="dataSource"/></property>   
  91.     </bean>   
  92.        
  93.     <!-- 异常处理filter -->   
  94.     <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">   
  95.         <property name="authenticationEntryPoint">   
  96.             <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">   
  97.                 <property name="loginFormUrl" value="/acegilogin.jsp"/>   
  98.                 <property name="forceHttps" value="false"/>   
  99.             </bean>   
  100.         </property>   
  101.         <property name="accessDeniedHandler">   
  102.             <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">   
  103.                 <property name="errorPage" value="/accessDenied.jsp"/>   
  104.             </bean>   
  105.         </property>   
  106.     </bean>      
  107. </beans>  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
           default-autowire="byName" default-lazy-init="true">
	
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
	        <!-- 请自行修改为对应你的数据库的驱动类 -->
            <value>net.sourceforge.jtds.jdbc.Driver</value>            
        </property>
        <property name="url">
        	<!-- 请自行修改为对应你的数据库URL -->
            <value>jdbc:jtds:sqlserver://localhost:1433/javauser</value>
        </property>
        <property name="username">
            <value>sa</value>
        </property>
        <property name="password">
            <value>javauser</value>
        </property>
    </bean>
  
	<!-- ======================== FILTER CHAIN ======================= -->
	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
         <value>
		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
		    PATTERN_TYPE_APACHE_ANT
            /**=authenticationProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter
         </value>
      </property>
    </bean>   
    <!-- ======================== 认证filter ======================= -->
   
    <!-- 表单认证处理filter -->
	<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="/userinfo.jsp"/>
		<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
	</bean>
	
    <!-- 利用cookie自动登陆filter -->
	<bean id="rememberMeProcessingFilter"
          class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
        <property name="authenticationManager"
                  ref="authenticationManager"/>
        <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>    
	<bean id="rememberMeServices"
          class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="jdbcDaoImpl"/>
        <property name="key" value="javargb"/>
    </bean>  
    <bean id="rememberMeAuthenticationProvider"
          class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
        <property name="key" value="javargb"/>
    </bean>   
	
	<!-- 注销处理filter -->
	<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/acegilogin.jsp"/> <!-- URL redirected to after logout -->
      <constructor-arg>
         <list>
              <ref bean="rememberMeServices"/>
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
         </list>
      </constructor-arg>
   </bean>
	
   <!-- 认证管理器 -->
   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->
         <list>
            <ref local="daoAuthenticationProvider"/>
            <ref local="rememberMeAuthenticationProvider"/>
         </list>
      </property>
   </bean>   
	<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
		<property name="userDetailsService" ref="jdbcDaoImpl"/>		
	</bean>    
	
	<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
		<property name="dataSource"><ref bean="dataSource"/></property>
	</bean>
	
    <!-- 异常处理filter -->
	<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
		<property name="authenticationEntryPoint">
			<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>	
</beans>


OK,大功告成。 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值