1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Initial CAS support.

This commit is contained in:
Ben Alex
2004-04-19 07:34:32 +00:00
parent 782bfe5a74
commit fa9b872570
60 changed files with 5561 additions and 17 deletions
+606 -13
View File
@@ -294,7 +294,7 @@
handling each request. Handling involves a number of
operations:</para>
<itemizedlist spacing="compact">
<orderedlist>
<listitem>
<para>Store the configuration attributes that are associated with
each secure request.</para>
@@ -354,7 +354,7 @@
<para>Return any result received from the
<literal>SecurityInterceptorCallback</literal>.</para>
</listitem>
</itemizedlist>
</orderedlist>
<para>Whilst this may seem quite involved, don't worry. Developers
interact with the security process by simply implementing basic
@@ -854,6 +854,13 @@
<literal>AuthenticationProvider</literal> if you were not using
container adapters.</para>
</listitem>
<listitem>
<para><literal>CasAuthenticationProvider</literal> is able to
authenticate Yale Central Authentication Service (CAS) tickets.
This is discussed further in the CAS Single Sign On
section.</para>
</listitem>
</itemizedlist></para>
</sect2>
@@ -870,8 +877,26 @@
<para><programlisting>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
&lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
&lt;property name="saltSource"&gt;&lt;ref bean="saltSource"/&gt;&lt;/property&gt;
&lt;property name="passwordEncoder"&gt;&lt;ref bean="passwordEncoder"/&gt;&lt;/property&gt;
&lt;/bean&gt;</programlisting></para>
<para>The <literal>PasswordEncoder</literal> and
<literal>SaltSource</literal> are optional. A
<literal>PasswordEncoder</literal> provides encoding and decoding of
passwords obtained from the authentication repository. A
<literal>SaltSource</literal> enables the passwords to be populated
with a "salt", which enhances the security of the passwords in the
authentication repository. <literal>PasswordEncoder</literal>
implementations are provided with the Acegi Security System for Spring
covering MD5, SHA and cleartext encodings. Two
<literal>SaltSource</literal> implementations are also provided:
<literal>SystemWideSaltSource</literal> which encodes all passwords
with the same salt, and <literal>ReflectionSaltSource</literal>, which
inspects a given property of the returned User object to obtain the
salt. Please refer to the JavaDocs for further details on these
optional features.</para>
<para>For a class to be able to provide the
<literal>DaoAuthenticationProvider</literal> with access to an
authentication repository, it must implement the
@@ -957,10 +982,13 @@
<para>You can use different relational database management systems by
modifying the <literal>DriverManagerDataSource</literal> shown above.
Irrespective of the database used, a standard schema must be used as
indicated in <literal>dbinit.txt</literal>. Of particular note is the
database must return responses that treat the username as case
insensitive, in order to comply with the
<literal>AuthenticationDao</literal> contract.</para>
indicated in <literal>dbinit.txt</literal>.</para>
<para>If you default schema is unsuitable for your needs,
<literal>JdbcDaoImpl</literal> provides two properties that allow
customisation of the SQL statements. You may also subclass the
<literal>JdbcDaoImpl</literal> if further customisation is necessary.
Please refer to the JavaDocs for details.</para>
<para>The Acegi Security System for Spring ships with a Hypersonic SQL
instance that has the required authentication information and sample
@@ -1487,11 +1515,13 @@ public boolean supports(Class clazz);</programlisting></para>
<literal>HttpSession</literal> object and filters to authenticate the
user. Another approach is HTTP Basic Authentication, which allows
clients to use HTTP headers to present authentication information to
the Acegi Security System for Spring. The final approach is via
Container Adapters, which allow supported web containers to perform
the authentication themselves. HTTP Session Authentication is
discussed below, whilst Container Adapters are discussed in a separate
section.</para>
the Acegi Security System for Spring. Alternatively, you can also use
Yale Central Authentication Service (CAS) for enterprise-wide single
sign on. The final approach is via Container Adapters, which allow
supported web containers to perform the authentication themselves.
HTTP Session and Basic Authentication is discussed below, whilst CAS
and Container Adapters are discussed in separate sections of this
document.</para>
</sect2>
<sect2 id="security-ui-http-session">
@@ -1538,7 +1568,7 @@ public boolean supports(Class clazz);</programlisting></para>
<literal>authenticationFailureUrl</literal>. The
<literal>AuthenticationException</literal> will be placed into the
<literal>HttpSession</literal> attribute indicated by
<literal>AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY</literal>,
<literal>AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY</literal>,
enabling a reason to be provided to the user on the error page.</para>
<para>If authentication is successful, the resulting
@@ -1552,7 +1582,7 @@ public boolean supports(Class clazz);</programlisting></para>
browser will need to be redirected to the target URL. The target URL
is usually indicated by the <literal>HttpSession</literal> attribute
specified by
<literal>AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY</literal>.
<literal>AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY</literal>.
This attribute is automatically set by the
<literal>SecurityEnforcementFilter</literal> when an
<literal>AuthenticationException</literal> occurs, so that after login
@@ -2100,6 +2130,569 @@ $CATALINA_HOME/bin/startup.sh</programlisting></para>
</sect2>
</sect1>
<sect1 id="security-cas">
<title>Yale Central Authentication Service (CAS) Single Sign On</title>
<sect2 id="security-cas-overview">
<title>Overview</title>
<para>Yale University produces an enterprise-wide single sign on
system known as CAS. Unlike other initiatives, Yale's Central
Authentication Service is open source, widely used, simple to
understand, platform independent, and supports proxy capabilities. The
Acegi Security System for Spring fully supports CAS, and provides an
easy migration path from single-application deployments of Acegi
Security through to multiple-application deployments secured by an
enterprise-wide CAS server.</para>
<para>You can learn more about CAS at
<literal>http://www.yale.edu/tp/auth/</literal>. You will need to
visit this URL to download the CAS Server files. Whilst the Acegi
Security System for Spring includes two CAS libraries in the
"-with-dependencies" ZIP file, you will still need the CAS Java Server
Pages and <literal>web.xml</literal> to customise and deploy your CAS
server.</para>
</sect2>
<sect2 id="security-cas-how-cas-works">
<title>How CAS Works</title>
<para>Whilst the CAS web site above contains two documents that detail
the architecture of CAS, we present the general overview again here
within the context of the Acegi Security System for Spring. The
following refers to CAS 2.0, being the version of CAS that Acegi
Security for Spring supports.</para>
<para>Somewhere in your enterprise you will need to setup a CAS
server. The CAS server is simply a standard WAR file, so there isn't
anything difficult about setting up your server. Inside the WAR file
you will customise the login and other single sign on pages displayed
to users. You will also need to specify in the web.xml a
<literal>PasswordHandler</literal>. The
<literal>PasswordHandler</literal> has a simple method that returns a
boolean as to whether a given username and password is valid. Your
<literal>PasswordHandler</literal> implementation will need to link
into some type of backend authentication repository, such as an LDAP
server or database. </para>
<para>If you're running an existing CAS server, you will have already
established a <literal>PasswordHandler</literal>. If you have not,
might prefer to use the Acegi Security System for Spring
<literal>CasPasswordHandler</literal> class. This class delegates
through to the standard Acegi Security
<literal>AuthenticationManager</literal>, enabling you to use a
security configuration you might already have in place. You do not
need to use the <literal>CasPasswordHandler</literal> class on your
CAS server unless you do not wish. The Acegi Security System for
Spring will function as a CAS client successfully irrespective of the
<literal>PasswordHandler</literal> you've chosen for your CAS
server.</para>
<para>Apart from the CAS server itself, the other key player is of
course the secure web applications deployed throughout your
enterprise. These web applications are known as "services". There are
two types of services: standard services and proxy services. A proxy
service is able to request resources from other services on behalf of
the user. This will be explained more fully later.</para>
<para>Services can be developed in a large variety of languages, due
to CAS 2.0's very light XML-based protocol. The Yale CAS home page
contains a clients archive which demonstrates CAS clients in Java,
Active Server Pages, Perl, Python and others. Naturally, Java support
is very strong given the CAS server is written in Java. You do not
need to use one of CAS' clients to interact with the CAS server from
Acegi Security System for Spring secured applications. This is handled
transparently for you.</para>
<para>The basic interaction between a web browser, CAS server and an
Acegi Security for System Spring secured service is as follows:</para>
<orderedlist>
<listitem>
<para>The web user is browsing the service's public pages. CAS or
Acegi Security is not involved.</para>
</listitem>
<listitem>
<para>The user eventually requests a page that is either secure or
one of the beans it uses is secure. Acegi Security's
SecurityEnforcementFilter will detect the
AuthenticationException.</para>
</listitem>
<listitem>
<para>Because the user has no <literal>Authentication</literal>
object in
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>,
the SecurityEnforcementFilter will call the configured
<literal>AuthenticationEntryPoint</literal>. If using CAS, this
will be the <literal>CasProcessingFilterEntryPoint</literal>
class.</para>
</listitem>
<listitem>
<para>The CasProcessingFilterEntry point will redirect the user's
browser to the CAS server. It will also indicate a
<literal>service</literal> parameter, which is the callback URL
for the Acegi Security service. For example, the URL the browser
is redirected to might be
<literal>https://my.company.com/cas/login?service=https://server3.company.com/webapp/j_acegi_cas_security_check</literal>.</para>
</listitem>
<listitem>
<para>After the user's browser redirects to CAS, they will be
prompted for their username and password. If the user presents a
session cookie which indicates they've previously logged on, they
will not be prompted to login again (there is an exception to this
procedure, which we'll cover later). CAS will use the
PasswordHandler discussed above to decide whether the username and
password is valid</para>
</listitem>
<listitem>
<para>Upon successful login, CAS will redirect the user's browser
back to the original service. It will also include a
<literal>ticket</literal> parameter, which is an opaque string
representing the "service ticket". Continuing our earlier example,
the URL the browser is redirected to might be
<literal>https://server3.company.com/webapp/j_acegi_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</literal>.</para>
</listitem>
<listitem>
<para>Back in the service web application, the
<literal>CasProcessingFilter</literal> is always listening for
requests to <literal>/j_acegi_cas_security_check</literal> (this
is configurable, but we'll use the defaults in this introduction).
The processing filter will construct a
<literal>UsernamePasswordAuthenticationToken</literal>
representing the service ticket. The principal will be equal to
<literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>,
whilst the credentials will be the service ticket opaque value.
This authentication request will then be handed to the configured
<literal>AuthenticationManager</literal>.</para>
</listitem>
<listitem>
<para>The AuthenticationManager implementation will be the
<literal>ProviderManager</literal>, which is in turn configured
with the <literal>CasAuthenticationProvider</literal>. The
<literal>CasAuthenticationProvider</literal> only responds to
<literal>UsernamePasswordAuthenticationToken</literal>s containing
the CAS-specific principal (such as
<literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>)
and <literal>CasAuthenticationToken</literal>s (discussed
later).</para>
</listitem>
<listitem>
<para><literal>CasAuthenticationProvider</literal> will validate
the service ticket using a <literal>TicketValidator</literal>
implementation. Acegi Security includes one implementation, the
<literal>CasProxyTicketValidator</literal>. This implementation
uses a CAS-supplied ticket validator. The
<literal>CasProxyTicketValidator</literal> makes a HTTPS request
to the CAS server in order to validate the service ticket. The
<literal>CasProxyTicketValidator</literal> may also include a
proxy callback parameter, which is included in this example:
<literal>https://my.company.com/cas/proxyValidate?service=https://server3.company.com/webapp/j_acegi_cas_security_check&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/casProxy/receptor</literal>.</para>
</listitem>
<listitem>
<para>Back of the CAS server, the proxy validation request will be
received. If the presented service ticket matches the service URL
requested initially, CAS will provide an affirmative response in
XML indicating the username. If any proxy was involved in the
authentication (discussed below), the list of proxies is also
included in the XML response.</para>
</listitem>
<listitem>
<para>[OPTIONAL] If the request to the CAS validation service
included the <literal>pgtUrl</literal>, CAS will include a
<literal>pgtIou</literal> string in the XML response. This
<literal>pgtIou</literal> represents a proxy-granting ticket IOU.
The CAS server will then create its own HTTPS connection back to
the <literal>pgtUrl</literal>. This is to mutually authenticate
the CAS server and the claimed service. The HTTPS connection will
be used to send a proxy granting ticket to the original web
application. For example,
<literal>https://server3.company.com/webapp/casProxy/receptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</literal>.
We suggest you use CAS' <literal>ProxyTicketReceptor</literal>
servlet to receive these proxy-granting tickets, if they are
required.</para>
</listitem>
<listitem>
<para>The <literal>CasProxyTicketValidator</literal> will parse
the XML received from the CAS server. It will return to the
<literal>CasAuthenticationProvider</literal> a
<literal>TicketResponse</literal>, which includes the username
(mandatory), proxy list (if any were involved), and proxy-granting
ticket IOU (if the proxy callback was requested).</para>
</listitem>
<listitem>
<para>Next <literal>CasAuthenticationProvider</literal> will call
a configured <literal>CasProxyDecider</literal>. The
<literal>CasProxyDecider</literal> indicates whether the proxy
list in the <literal>TicketResponse</literal> is acceptable to the
service. Several implementations are provided with the Acegi
Security System: <literal>RejectProxyTickets</literal>,
<literal>AcceptAnyCasProxy</literal> and
<literal>NamedCasProxyDecider</literal>. These names are largely
self-explanatory, except <literal>NamedCasProxyDecider</literal>
which allows a <literal>List</literal> of trusted proxies to be
provided.</para>
</listitem>
<listitem>
<para><literal>CasAuthenticationProvider</literal> will next
request a <literal>CasAuthoritiesPopulator</literal> to advise the
<literal>GrantedAuthority</literal> objects that apply to the user
contained in the <literal>TicketResponse</literal>. Acegi Security
includes a <literal>DaoCasAuthoritiesPopulator</literal> which
simply uses the <literal>AuthenticationDao</literal>
infrastructure to find the <literal>User</literal> and their
associated <literal>GrantedAuthority</literal>s. Note that the
password and enabled/disabled status of <literal>User</literal>s
returned by the <literal>AuthenticationDao</literal> are ignored,
as the CAS server is responsible for authentication decisions.
<literal>DaoCasAuthoritiesPopulator</literal> is only concerned
with retrieving the <literal>GrantedAuthority</literal>s.</para>
</listitem>
<listitem>
<para>If there were no problems,
<literal>CasAuthenticationProvider</literal> constructs a
<literal>CasAuthenticationToken</literal> including the details
contained in the <literal>TicketResponse</literal> and the
<literal>GrantedAuthority</literal>s. The
<literal>CasAuthenticationToken</literal> contains the hash of a
key, so that the <literal>CasAuthenticationProvider</literal>
knows it created it.</para>
</listitem>
<listitem>
<para>Control then returns to
<literal>CasProcessingFilter</literal>, which places the created
<literal>CasAuthenticationToken</literal> into the
<literal>HttpSession</literal> attribute named
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.</para>
</listitem>
<listitem>
<para>The user's browser is redirected to the original page that
caused the <literal>AuthenticationException</literal>.</para>
</listitem>
<listitem>
<para>As the <literal>Authentication</literal> object is now in
the well-known location, it is handled like any other
authentication approach. Usually the
<literal>AutoIntegrationFilter</literal> will be used to associate
the <literal>Authentication</literal> object with the
<literal>ContextHolder</literal> for the duration of each
request.</para>
</listitem>
</orderedlist>
<para>It's good that you're still here! It might sound involved, but
you can relax as the Acegi Security System for Spring classes hide
much of the complexity. Let's now look at how this is
configured.</para>
</sect2>
<sect2 id="security-cas-install-server">
<title>CAS Server Installation (Optional)</title>
<para>As mentioned above, the Acegi Security System for Spring
includes a <literal>PasswordHandler</literal> that bridges your
existing <literal>AuthenticationManager</literal> into CAS. You do not
need to use this <literal>PasswordHandler</literal> to use Acegi
Security on the client side (any CAS
<literal>PasswordHandler</literal> will do).</para>
<para>To install, you will need to download and extract the CAS server
archive. We used version 2.0.12 Beta 3. There will be a
<literal>/web</literal> directory in the root of the deployment. Copy
an <literal>applicationContext.xml</literal> containing your
<literal>AuthenticationManager</literal> as well as the
<literal>CasPasswordHandler</literal> into the
<literal>/web/WEB-INF</literal> directory. A sample
<literal>applicationContext.xml</literal> is included below:</para>
<programlisting>&lt;bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl"&gt;
&lt;property name="userMap"&gt;
&lt;value&gt;
marissa=koala,ROLES_IGNORED_BY_CAS
dianne=emu,ROLES_IGNORED_BY_CAS
scott=wombat,ROLES_IGNORED_BY_CAS
peter=opal,disabled,ROLES_IGNORED_BY_CAS
&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
&lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
&lt;property name="providers"&gt;
&lt;list&gt;
&lt;ref bean="daoAuthenticationProvider"/&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casPasswordHandler" class="net.sf.acegisecurity.adapters.cas.CasPasswordHandler"&gt;
&lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>Note the granted authorities are ignored by CAS. It has no way
of communciating the granted authorities to calling applications. CAS
is only concerned with username and passwords.</para>
<para>Next you will need to edit the existing
<literal>/web/WEB-INF/web.xml</literal> file. Add (or edit in the case
of the <literal>authHandler</literal> property) the following
lines:</para>
<para><programlisting>&lt;context-param&gt;
&lt;param-name&gt;edu.yale.its.tp.cas.authHandler&lt;/param-name&gt;
&lt;param-value&gt;net.sf.acegisecurity.adapters.cas.CasPasswordHandlerProxy&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;/WEB-INF/applicationContext.xml&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;</programlisting></para>
<para>Copy the <literal>spring.jar</literal> and
<literal>acegi-security.jar</literal> files into
<literal>/web/WEB-INF/lib</literal>. Now use the <literal>ant
dist</literal> task in the <literal>build.xml</literal> in the root of
the directory structure. This will create
<literal>/lib/cas.war</literal>, which is ready for deployment to your
servlet container.</para>
</sect2>
<sect2 id="security-cas-install-client">
<title>CAS Acegi Security System Client Installation</title>
<para>The web application side of CAS is made easy due to the Acegi
Security System for Spring. It is assumed you already know the basics
of using the Acegi Security System for Spring, so these are not
covered again below. Only the CAS-specific beans are mentioned.</para>
<para>You will need to add a <literal>ServiceProperties</literal> bean
to your application context. This represents your service:</para>
<para><programlisting>&lt;bean id="serviceProperties" class="net.sf.acegisecurity.ui.cas.ServiceProperties"&gt;
&lt;property name="service"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/j_acegi_cas_security_check&lt;/value&gt;&lt;/property&gt;
&lt;property name="sendRenew"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;</programlisting></para>
<para>The <literal>service</literal> must equal a URL that will be
monitored by the <literal>CasProcessingFilter</literal>. The
<literal>sendRenew</literal> defaults to false, but should be set to
true if your application is particularly sensitive. What this
parameter does is tell the CAS login service that a single sign on
login is unacceptable. Instead, the user will need to re-enter their
username and password in order to gain access to the service.</para>
<para>The following beans should be configured to commence the CAS
authentication process:</para>
<para><programlisting>&lt;bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter"&gt;
&lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
&lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/casfailed.jsp&lt;/value&gt;&lt;/property&gt;
&lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/&lt;/value&gt;&lt;/property&gt;
&lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_acegi_cas_security_check&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"&gt;
&lt;property name="filterSecurityInterceptor"&gt;&lt;ref bean="filterInvocationInterceptor"/&gt;&lt;/property&gt;
&lt;property name="authenticationEntryPoint"&gt;&lt;ref bean="casProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint"&gt;
&lt;property name="loginUrl"&gt;&lt;value&gt;https://localhost:8443/cas/login&lt;/value&gt;&lt;/property&gt;
&lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
&lt;/bean&gt;</programlisting></para>
<para>You will also need to add the
<literal>CasProcessingFilter</literal> to web.xml:</para>
<para><programlisting>&lt;filter&gt;
&lt;filter-name&gt;Acegi CAS Processing Filter&lt;/filter-name&gt;
&lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;net.sf.acegisecurity.ui.cas.CasProcessingFilter&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi CAS Processing Filter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</programlisting></para>
<para>The <literal>CasProcessingFilter</literal> has very similar
properties to the <literal>AuthenticationProcessingFilter</literal>
(used for form-based logins). Each property is
self-explanatory.</para>
<para>For CAS to operate, the
<literal>SecurityEnforcementFilter</literal> must have its
<literal>authenticationEntryPoint</literal> property set to the
<literal>CasProcessingFilterEntryPoint</literal> bean. </para>
<para>The <literal>CasProcessingFilterEntryPoint</literal> must refer
to the <literal>ServiceProperties</literal> bean (discussed above) and
provide the URL to the enterprise's CAS login server. This is where
the user's browser will be redirected.</para>
<para>Next you need to add an <literal>AuthenticationManager</literal>
that uses <literal>CasAuthenticationProvider</literal> and its
collaborators:</para>
<para><programlisting>&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
&lt;property name="providers"&gt;
&lt;list&gt;
&lt;ref bean="casAuthenticationProvider"/&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider"&gt;
&lt;property name="casAuthoritiesPopulator"&gt;&lt;ref bean="casAuthoritiesPopulator"/&gt;&lt;/property&gt;
&lt;property name="casProxyDecider"&gt;&lt;ref bean="casProxyDecider"/&gt;&lt;/property&gt;
&lt;property name="ticketValidator"&gt;&lt;ref bean="casProxyTicketValidator"/&gt;&lt;/property&gt;
&lt;property name="statelessTicketCache"&gt;&lt;ref bean="statelessTicketCache"/&gt;&lt;/property&gt;
&lt;property name="key"&gt;&lt;value&gt;my_password_for_this_auth_provider_only&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casProxyTicketValidator" class="net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator"&gt;
&lt;property name="casValidate"&gt;&lt;value&gt;https://localhost:8443/cas/proxyValidate&lt;/value&gt;&lt;/property&gt;
&lt;property name="proxyCallbackUrl"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/casProxy/receptor&lt;/value&gt;&lt;/property&gt;
&lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
&lt;!-- &lt;property name="trustStore"&gt;&lt;value&gt;/some/path/to/your/lib/security/cacerts&lt;/value&gt;&lt;/property&gt; --&gt;
&lt;/bean&gt;
&lt;bean id="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache"&gt;
&lt;property name="minutesToIdle"&gt;&lt;value&gt;20&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator"&gt;
&lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets"/&gt;</programlisting></para>
<para>The beans are all reasonable self-explanatory if you refer back
to the "How CAS Works" section. Careful readers might notice one
surprise: the <literal>statelessTicketCache</literal> property of the
<literal>CasAuthenticationProvider</literal>. This is discussed in
detail in the "Advanced CAS Usage" section.</para>
<para>Note the <literal>CasProxyTicketValidator</literal> has a
remarked out <literal>trustStore</literal> property. This property
might be helpful if you experience HTTPS certificate issues. Also note
the <literal>proxyCallbackUrl</literal> is set so the service can
receive a proxy-granting ticket. As mentioned above, this is optional
and unnecessary if you do not require proxy-granting tickets. If you
do use this feature, you will need to configure a suitable servlet to
receive the proxy-granting tickets. We suggest you use CAS'
<literal>ProxyTicketReceptor</literal> by adding the following to your
web application's <literal>web.xml</literal>:</para>
<para><programlisting>&lt;servlet&gt;
&lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
&lt;servlet-class&gt;edu.yale.its.tp.cas.proxy.ProxyTicketReceptor&lt;/servlet-class&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
&lt;url-pattern&gt;/casProxy/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;</programlisting></para>
<para>This completes the configuration of CAS. If you haven't made any
mistakes, your web application should happily work within the
framework of CAS single sign on. No other parts of the Acegi Security
System for Spring need to be concerned about the fact CAS handled
authentication.</para>
<para>There is also a <literal>contacts-cas.war</literal> file in the
sample applications directory. This sample application uses the above
settings and can be deployed to see CAS in operation.</para>
</sect2>
<sect2 id="security-cas-advanced-usage">
<title>Advanced CAS Usage</title>
<para>[DRAFT - COMMENTS WELCOME]</para>
<para>The <literal>CasAuthenticationProvider</literal> distinguishes
between stateful and stateless clients. A stateful client is
considered any that originates via the
<literal>CasProcessingFilter</literal>. A stateless client is any that
presents an authentication request via the
<literal>UsernamePasswordAuthenticationToken</literal> with a
principal equal to
<literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>.</para>
<para>Stateless clients are likely to be via remoting protocols such
as Hessian and Burlap. The <literal>BasicProcessingFilter</literal> is
still used in this case, but the remoting protocol client is expected
to present a username equal to the static string above, and a password
equal to a CAS service ticket. Clients should acquire a CAS service
ticket directly from the CAS server.</para>
<para>Because remoting protocols have no way of presenting themselves
within the context of a <literal>HttpSession</literal>, it isn't
possible to rely on the <literal>HttpSession</literal>'s
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>
attribute to locate the CasAuthenticationToken. Furthermore, because
the CAS server invalidates a service ticket after it has been
validated by the TicketValidator, presenting the same service ticket
on subsequent requests will not work. It is similarly very difficult
to obtain a proxy-granting ticket for a remoting protocol client, as
they are often operational on client machines which do not have HTTPS
certificates that would be trusted by the CAS server.</para>
<para>One obvious option is to not use CAS at all for remoting
protocol clients. However, this would eliminate many of the desirable
features of CAS.</para>
<para>As a middle-ground, the CasAuthenticationProvider uses a
StatelessTicketCache. This is used solely for requests with a
principal equal to
<literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>. What
happens is the CasAuthenticationProvider will store the resulting
CasAuthenticationToken in the StatelessTicketCache, keyed on the
service ticket. Accordingly, remoting protocol clients can present the
same service ticket and the CasAuthenticationProvider will not need to
contact the CAS server for validation.</para>
<para>The other aspect of advanced CAS usage involves creating proxy
tickets from the proxy-granting ticket. As indicated above, we
recommend you use CAS' <literal>ProxyTicketReceptor</literal> to
receive these tickets. The <literal>ProxyTicketReceptor</literal>
provides a static method that enables you to obtain a proxy ticket by
presenting the proxy-granting IOU ticket. You can obtain the
proxy-granting IOU ticket by calling
<literal>CasAuthenticationToken.getProxyGrantingTicketIou()</literal>.</para>
<para>It is hoped you find CAS integration easy and useful with the
Acegi Security System for Spring classes. Welcome to enterprise-wide
single sign on!</para>
</sect2>
</sect1>
<sect1 id="security-sample">
<title>Contacts Sample Application</title>