SEC-282: Tutorial for securing Petclinic using Acegi Security.

This commit is contained in:
Ben Alex 2006-05-31 07:40:45 +00:00
parent 00620b6992
commit 7957d54d67
2 changed files with 167 additions and 83 deletions

View File

@ -5,7 +5,8 @@
<body>
<h1>Tutorial: Adding Security to Spring Petclinic</h1>
<h2>Background requirements</h2>
<h2>Preparation</h2>
<p>To complete this tutorial, you will require a servlet container (such as Tomcat)
and a general understanding of using Spring without Acegi Security. The Petclinic
@ -14,11 +15,13 @@ only try to learn one thing at a time, and start with Spring/Petclinic before
Acegi Security.
</p>
<h2>Download</h2>
<p>
You will also need to download:
<ul>
<li>Spring 2.0 M4 with dependencies ZIP file</li>
<li>Acegi Security 1.0.0</li>
</ul>
</p>
<p>
Unzip both files. After unzipping Acegi Security, you'll need to unzip the
@ -29,7 +32,83 @@ unzipped WAR, not the original ZIP). There is no need to setup any environment
variables to complete the tutorial.
</p>
<h2>Setup database</h2>
<h2>Add required Acegi Security files to Petclinic</h2>
<p>
We now need to put some extra files into Petclinic. The following commands should work:
<pre>
mkdir %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
copy %acegi%\accessDenied.jsp %spring%\samples\petclinic\war
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
</pre>
</p>
<h2>Configure Petclinic's files</h2>
<p>Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code.
<pre>
&lt;filter&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;org.acegisecurity.util.FilterChainProxy&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
The resulting block will look like this:
<pre>
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;
/WEB-INF/applicationContext-jdbc.xml
/WEB-INF/applicationContext-acegi-security.xml
&lt;/param-value&gt;
&lt;/context-param&gt;
</pre>
</p>
<p>
To make it easier to experiment with the application, now edit
%spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown:
<pre>
&lt;table style="width:100%"&gt;&lt;tr&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/welcome.htm"/&gt;"&gt;Home&lt;/A&gt;&lt;/td&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/j_acegi_logout"/&gt;"&gt;Logout&lt;/A&gt;&lt;/td&gt;
&lt;td style="text-align:right;color:silver"&gt;PetClinic :: a Spring Framework demonstration&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</pre>
</p>
<p>
Our last step is to specify which URLs require authorization and which do not. Let's
edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml.
Locate the bean definition for FilterSecurityInterceptor. Edit its objectDefinitionSource
property so that it reflects the following:
<pre>
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
&lt;/value&gt;
&lt;/property&gt;
</pre>
</p>
<h2>Start Petclinic's database</h2>
<p>Start the Hypersonic server (this is just normal Petclinic configuration):
<pre>
@ -46,88 +125,11 @@ build setupDB
</pre>
</p>
<h2>Setup Petclinic's web.xml</h2>
<p>Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code.
<pre>
&lt;filter&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;org.acegisecurity.util.FilterChainProxy&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
The resulting block will look like this:
<pre>
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;
/WEB-INF/applicationContext-jdbc.xml
/WEB-INF/applicationContext-acegi-security.xml
&lt;/param-value&gt;
&lt;/context-param&gt;
</pre>
</p>
<h2>Add the necessary files</h2>
<p>
We now need to put some extra files into Petclinic. The following commands should work:
<pre>
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
</pre>
</p>
<p>
To make it easier to experiment with the application, let's edit
%spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown:
<pre>
&lt;table style="width:100%"&gt;&lt;tr&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/welcome.htm"/&gt;"&gt;Home&lt;/A&gt;&lt;/td&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/j_acegi_logout"/&gt;"&gt;Logout&lt;/A&gt;&lt;/td&gt;
&lt;td style="text-align:right;color:silver"&gt;PetClinic :: a Spring Framework demonstration&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</pre>
</p>
<h2>Modify the allowed URLs</h2>
<p>
Our last step is to specify which URLs require authorization and which do not. Let's
edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml.
Scroll to the bottom and locate the bean definition for FilterSecurityInterceptor.
Edit its objectDefinitionSource property so that it reflects the following:
<pre>
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
&lt;/value&gt;
&lt;/property&gt;
</pre>
</p>
<h2>Build and deploy the Petclinic WAR file</h2>
<p>
Use the Ant build and deploy to your servlet container:
Use Petclinic's Ant build script and deploy to your servlet container:
<pre>
cd %spring%\samples\petclinic
build warfile
@ -138,12 +140,83 @@ copy dist\petclinic.war %TOMCAT_HOME%\webapps
<p>Finally, start your container and try to visit the home page.
Your request should be intercepted and you will be forced to login.</p>
<h2>Optional Bonus: Securing the Middle Tier</h2>
<p>
Whilst you've now secured your web requests, you might want to stop users
from being able to add clinic visits unless authorized. We'll make it so
you need to hold ROLE_SUPERVISOR to add a clinic visit.
</p>
<p>
In %spring%\samples\petclinic\war\WEB-INF\applicationContext-jdbc.xml, locate
the TransactionProxyFactoryBean definition. Add an additional property after
the existing "preInterceptors" property:
<pre>
&lt;property name="postInterceptors" ref="methodSecurityInterceptor"/&gt;
</pre>
</p>
<p>
Finally, we need to add in the referred-to "methodSecurityInterceptor" bean definition.
So pop an extra bean definition in, as shown below:
<pre>
&lt;bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
&lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
&lt;property name="accessDecisionManager"&gt;
&lt;bean class="org.acegisecurity.vote.AffirmativeBased"&gt;
&lt;property name="allowIfAllAbstainDecisions" value="false"/&gt;
&lt;property name="decisionVoters"&gt;
&lt;list&gt;
&lt;bean class="org.acegisecurity.vote.RoleVoter"/&gt;
&lt;bean class="org.acegisecurity.vote.AuthenticatedVoter"/&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED
org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR
&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
</pre>
</p>
<p>
Redeploy your web application. Use the earlier process to do that. Be careful to
ensure that the old Petclinic WAR is replaced by the new Petclinic WAR in your
servlet container. Login as "marissa", who has ROLE_SUPERVISOR. You will be able to
then view a customer and add a visit. Logout, then login as anyone other than Marissa.
You will receive an access denied error when you attempt to add a visit.
</p>
<p>
To clean things up a bit, you might want to wrap up by hiding the "add visit" link
unless you are authorized to use it. Acegi Security provides a tag library to help
you do that. Edit %spring%\samples\petclinic\war\WEB-INF\jsp\owner.jsp. Add
the following line to the top of the file:
<pre>
&lt;%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %&gt;
</pre>
Next, scroll down and find the link to "add visit". Modify it as follows:
<pre>
&lt;authz:authorize ifAllGranted="ROLE_SUPERVISOR"&gt;
&lt;FORM method=GET action="&lt;c:url value="/addVisit.htm"/&gt;" name="formVisitPet&lt;c:out value="${pet.id}"/&gt;"&gt;
&lt;INPUT type="hidden" name="petId" value="&lt;c:out value="${pet.id}"/&gt;"/&gt;
&lt;INPUT type="submit" value="Add Visit"/&gt;
&lt;/FORM&gt;
&lt;/authz:authorize&gt;
</pre>
</p>
<h2>What now?</h2>
<p>
These steps can be applied to your own application. Although we do suggest
that you visit <a href="http://acegisecurity.org">http://acegisecurity.org</a>
and in particular review the "Suggested Steps" for getting started with Acegi
Security.</p>
Security. The suggested steps are optimized for learning Acegi Security quickly
and applying it to your own projects. It also includes realistic time estimates
for each step so you can plan your integration activities.</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
set spring=C:\dev\spring-framework-2.0-m4
set acegi=C:\dev\eclipse\workspaces\acegi\acegisecurity\samples\tutorial\target\acegi-security-sample-tutorial
mkdir %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
copy %acegi%\accessDenied.jsp %spring%\samples\petclinic\war
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib