SEC-1717: Document how to perform Single Logout with CAS and added integration test for sample application to test Single Logout

This commit is contained in:
Rob Winch 2011-04-16 20:17:01 -05:00
parent 04f1df2a1b
commit 11331d34d9
2 changed files with 92 additions and 0 deletions

View File

@ -307,6 +307,83 @@
need to be concerned about the fact CAS handled authentication. In the following sections
we will discuss some (optional) more advanced configurations.</para>
</section>
<section xml:id="cas-singlelogout">
<info>
<title>Single Logout</title>
</info>
<para>The CAS protocol supports Single Logout and can be easily added to your Spring
Security configuration. Below are updates to the Spring Security configuration
that handle Single Logout <programlisting language="xml"><![CDATA[
<security:http entry-point-ref="casEntryPoint">
...
<security:logout logout-success-url="/cas-logout.jsp"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>
<!-- This filter handles a Single Logout Request from the CAS Server -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
<!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="https://localhost:9443/cas/logout"/>
<constructor-arg>
<bean
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="filterProcessesUrl" value="/j_spring_cas_security_logout"/>
</bean>
]]></programlisting> The <literal>logout</literal> element logs the user out of the local application, but
does not terminate the session with the CAS server or any other applications that have been logged
into. The <literal>requestSingleLogoutFilter</literal> filter will allow the url of
<literal>/spring_security_cas_logout</literal> to be requested to redirect the application to the
configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the
services that were signed into. The <literal>singleLogoutFilter</literal> handles the Single Logout
request by looking up the <literal>HttpSession</literal> in a static <interfacename>Map</interfacename>
and then invalidating it.</para>
<para>It might be confusing why both the <literal>logout</literal> element and the
<literal>singleLogoutFilter</literal> are needed. It is considered best practice to logout locally
first since the <literal>SingleSignOutFilter</literal> just stores the
<interfacename>HttpSession</interfacename> in a static <interfacename>Map</interfacename> in order to
call invalidate on it. With the configuration above, the flow of logout would be:
<orderedlist inheritnum="ignore" continuation="restarts">
<listitem>The user requests <literal>/j_spring_security_logout</literal> which would log the user
out of the local application and send the user to the logout success page.</listitem>
<listitem>The logout success page, <literal>/cas-logout.jsp</literal>, should instruct the user
to click a link pointing to <literal>/j_spring_cas_security_logout</literal> in order to logout
out of all applications.</listitem>
<listitem>When the user clicks the link, the user is redirected to the CAS single logout URL
(<literal>https://localhost:9443/cas/logout</literal>).</listitem>
<listitem>On the CAS Server side, the CAS single logout URL then submits single logout requests to
all the CAS Services. On the CAS Service side, JASIG's
<classname>SingleSignOutFilter</classname> processes the logout request by invaliditing the
original session.</listitem>
</orderedlist>
</para>
<para>The next step is to add the following to your web.xml
<programlisting language="xml"><![CDATA[
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>]]></programlisting></para>
<para>When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is
recommended to add the <classname>CharacterEncodingFilter</classname> to ensure that the character
encoding is correct when using the <classname>SingleSignOutFilter</classname>. Again, refer to JASIG's
documentation for details. The <classname>SingleSignOutHttpSessionListener</classname> ensures that
when an <interfacename>HttpSession</interfacename> expires, the mapping used for single logout is
removed.</para>
</section>
<section xml:id="cas-pt">
<info>
<title>Proxy Ticket Authentication</title>

View File

@ -21,6 +21,7 @@ import org.junit.runner.RunWith;
import org.spockframework.runtime.Sputnik;
import org.springframework.security.samples.cas.pages.*
import spock.lang.Shared;
import spock.lang.Stepwise;
/**
@ -30,6 +31,7 @@ import spock.lang.Stepwise;
*/
@Stepwise
class CasSampleSpec extends BaseSpec {
@Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout')
def 'access home page with unauthenticated user succeeds'() {
when: 'Unauthenticated user accesses the Home Page'
@ -108,4 +110,17 @@ class CasSampleSpec extends BaseSpec {
then: 'login page is displayed'
at LoginPage
}
def 'loging out of the cas server successfully logs out of the cas servers'() {
setup: 'login with ROLE_USER'
to SecurePage
at LoginPage
login 'rod'
at SecurePage
when: 'logout of the CAS Server'
go casServerLogoutUrl
to SecurePage
then: 'user is logged out of the CAS Service'
at LoginPage
}
}