From Gossip@caterpillar

Acegi Gossip: 第一個Acegi 程式 - 登出、自動Cookies登入





在完成 第一個Acegi 程式 - 表單網頁 之後,您已經可以使用Acegi來保護您所設定的資源,為了方便起見,您應該提供一個登出的鏈結,讓使用者可以登出,讓目前的對話失效。

這可以在/WEB-INF/loginsuccess.jsp上加上一個登出的鏈結,動作的目的地是j_acegi_logout:
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登入成功</title>
</head>
<body>

<h1>歡迎 <%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY) %>
</h1>
<br><a href="../j_acegi_logout">登出</a>
</body>
</html>

要進行登出,可以設定org.acegisecurity.ui.logout.LogoutFilter,指定登出後的顯示頁面,以及執行登出動作的處理者:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
... 先前設定相同

<!-- 登出處理 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/acegilogin.jsp"/> <!-- 登出後的顯示頁面 -->
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</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,exceptionTranslationFilter,filterSecurityInterceptor,logoutFilter
</value>
</property>
</bean>
</beans>

這樣就OK了,登入之後,您就可以看到登出的鏈結,按下該鏈結後就可自動進行登出。

如果要執行Cookies自動登入,則可以使用org.acegisecurity.ui.rememberme.RememberMeProcessingFilter,您要提供驗證管理員與RememberMeServices,並指定Cookie名稱,例如:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
....

<!-- 驗證管理員,管理驗證資訊提供者 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers"><!-- 可有多個提供者,其中一個驗證通過即可以了 -->
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>

.....

<!-- 利用cookie自動登入 -->
<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="javauser"/>
</bean>
<bean id="rememberMeAuthenticationProvider"
class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="javauser"/>
</bean>

<!-- 登出處理 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/acegilogin.jsp"/> <!-- 登出後的顯示頁面 -->
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</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
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,
filterSecurityInterceptor,logoutFilter,rememberMeProcessingFilter
</value>
</property>
</bean>
</beans>

要進行自動登入,您必須在登入時發送_acegi_security_remember_me請求參數,例如修改acegilogin.jsp:
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
<head>
<title>Acegi 範例網頁 - 登入</title>
</head>
<body>
<h2>登入範例應用程式!</h2>
<br />
<form action="j_acegi_security_check" method="POST">
<table>
<tr>
<td>名稱:</td>
<td><input type='text' name='j_username' value=''></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><input name="reset" type="reset"></td>
<td><input name="submit" type="submit"></td>
</tr>
</table>
</form>
</body>
</html>