|
@@ -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><bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
|
|
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
|
|
+ <property name="saltSource"><ref bean="saltSource"/></property>
|
|
|
+ <property name="passwordEncoder"><ref bean="passwordEncoder"/></property>
|
|
|
</bean></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&ticket=ST-0-ER94xMJmn6pha35CQRoZ&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&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><bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
|
|
+ <property name="userMap">
|
|
|
+ <value>
|
|
|
+ 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
|
|
|
+ </value>
|
|
|
+ </property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
|
|
+ <property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
|
|
+ <property name="providers">
|
|
|
+ <list>
|
|
|
+ <ref bean="daoAuthenticationProvider"/>
|
|
|
+ </list>
|
|
|
+ </property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casPasswordHandler" class="net.sf.acegisecurity.adapters.cas.CasPasswordHandler">
|
|
|
+ <property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
|
|
+</bean></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><context-param>
|
|
|
+ <param-name>edu.yale.its.tp.cas.authHandler</param-name>
|
|
|
+ <param-value>net.sf.acegisecurity.adapters.cas.CasPasswordHandlerProxy</param-value>
|
|
|
+</context-param>
|
|
|
+
|
|
|
+<context-param>
|
|
|
+ <param-name>contextConfigLocation</param-name>
|
|
|
+ <param-value>/WEB-INF/applicationContext.xml</param-value>
|
|
|
+</context-param>
|
|
|
+
|
|
|
+<listener>
|
|
|
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
|
|
+</listener></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><bean id="serviceProperties" class="net.sf.acegisecurity.ui.cas.ServiceProperties">
|
|
|
+ <property name="service"><value>https://localhost:8443/contacts-cas/j_acegi_cas_security_check</value></property>
|
|
|
+ <property name="sendRenew"><value>false</value></property>
|
|
|
+</bean></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><bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter">
|
|
|
+ <property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
|
|
+ <property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
|
|
|
+ <property name="defaultTargetUrl"><value>/</value></property>
|
|
|
+ <property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
|
|
|
+ <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
|
|
|
+ <property name="authenticationEntryPoint"><ref bean="casProcessingFilterEntryPoint"/></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
|
|
|
+ <property name="loginUrl"><value>https://localhost:8443/cas/login</value></property>
|
|
|
+ <property name="serviceProperties"><ref bean="serviceProperties"/></property>
|
|
|
+</bean></programlisting></para>
|
|
|
+
|
|
|
+ <para>You will also need to add the
|
|
|
+ <literal>CasProcessingFilter</literal> to web.xml:</para>
|
|
|
+
|
|
|
+ <para><programlisting><filter>
|
|
|
+ <filter-name>Acegi CAS Processing Filter</filter-name>
|
|
|
+ <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
|
|
+ <init-param>
|
|
|
+ <param-name>targetClass</param-name>
|
|
|
+ <param-value>net.sf.acegisecurity.ui.cas.CasProcessingFilter</param-value>
|
|
|
+ </init-param>
|
|
|
+</filter>
|
|
|
+
|
|
|
+<filter-mapping>
|
|
|
+ <filter-name>Acegi CAS Processing Filter</filter-name>
|
|
|
+ <url-pattern>/*</url-pattern>
|
|
|
+</filter-mapping></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><bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
|
|
+ <property name="providers">
|
|
|
+ <list>
|
|
|
+ <ref bean="casAuthenticationProvider"/>
|
|
|
+ </list>
|
|
|
+ </property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider">
|
|
|
+ <property name="casAuthoritiesPopulator"><ref bean="casAuthoritiesPopulator"/></property>
|
|
|
+ <property name="casProxyDecider"><ref bean="casProxyDecider"/></property>
|
|
|
+ <property name="ticketValidator"><ref bean="casProxyTicketValidator"/></property>
|
|
|
+ <property name="statelessTicketCache"><ref bean="statelessTicketCache"/></property>
|
|
|
+ <property name="key"><value>my_password_for_this_auth_provider_only</value></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casProxyTicketValidator" class="net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
|
|
|
+ <property name="casValidate"><value>https://localhost:8443/cas/proxyValidate</value></property>
|
|
|
+ <property name="proxyCallbackUrl"><value>https://localhost:8443/contacts-cas/casProxy/receptor</value></property>
|
|
|
+ <property name="serviceProperties"><ref bean="serviceProperties"/></property>
|
|
|
+ <!-- <property name="trustStore"><value>/some/path/to/your/lib/security/cacerts</value></property> -->
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache">
|
|
|
+ <property name="minutesToIdle"><value>20</value></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
|
|
|
+ <property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
|
|
+</bean>
|
|
|
+
|
|
|
+<bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets"/></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><servlet>
|
|
|
+ <servlet-name>casproxy</servlet-name>
|
|
|
+ <servlet-class>edu.yale.its.tp.cas.proxy.ProxyTicketReceptor</servlet-class>
|
|
|
+</servlet>
|
|
|
+
|
|
|
+<servlet-mapping>
|
|
|
+ <servlet-name>casproxy</servlet-name>
|
|
|
+ <url-pattern>/casProxy/*</url-pattern>
|
|
|
+</servlet-mapping></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>
|
|
|
|