Added Michael's updated petclinic tutorial

This commit is contained in:
Luke Taylor 2008-04-04 23:03:13 +00:00
parent a43d054bd7
commit e5956c2935
1 changed files with 79 additions and 80 deletions

View File

@ -19,39 +19,45 @@ Tutorial: Adding Security to Spring Petclinic
You will also need to download:
* Spring 2.0.6 with dependencies ZIP file
* Spring 2.5.2 with dependencies ZIP file
* Spring Security 2.0 M1
* Spring Security 2.0
Unzip both files. After unzipping Spring Security, you'll need to unzip the
spring-security-sample-tutorial.war file, because we need some files that are
included within it. In the code below, we'll refer to the respective unzipped
locations as %spring% and %acegi% (with the latter variable referring to the
unzipped WAR, not the original ZIP). There is no need to setup any environment
variables to complete the tutorial.
spring-security-sample-tutorial-2.0.war file, because we need some files that are
included within it. After unzipping the war file, you will see a folder called
spring-security-samples-tutorial-2.0.0.
In the code below, we'll refer to the respective unzipped
locations as %spring% and %spring-sec-tutorial% (with the later variable
referring to the unzipped WAR, not the original ZIP). There is no need to setup
any environment variables to complete the tutorial.
* Add required Spring Security files to Petclinic
We now need to put some extra files into Petclinic. The following commands should work:
We now need to put some extra files into Petclinic.
The following example is based on Windows MS-DOS. It only involves file copy and folder creation.
You can adapt it on any operating system.
+------------------------------------------------------
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
copy %spring-sec-tutorial%\WEB-INF\applicationContext-security-ns.xml %spring%\samples\petclinic\war\WEB-INF
copy %spring-sec-tutorial%\WEB-INF\lib\spring-security-core-2.0.0-RC1.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %spring-sec-tutorial%\WEB-INF\lib\spring-security-core-tiger-2.0.0-RC1.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %spring-sec-tutorial%\WEB-INF\lib\spring-security-acl-2.0.0-RC1.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %spring-sec-tutorial%\WEB-INF\lib\spring-security-taglibs-2.0.0-RC1.jar %spring%\samples\petclinic\war\WEB-INF\lib
copy %spring-sec-tutorial%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
+------------------------------------------------------
* Configure Petclinic's files
Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code.
It should be inserted right after the </context-param> end-tag.
+------------------------------------------------------
@ -67,7 +73,10 @@ copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WE
+------------------------------------------------------
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
Still inside web.xml, the "contextConfigLocation" specifies Spring configuration files that should be used
by the petclinic application. Locate the "contextConfigLocation" parameter, and add a new line into
the existing param-value. Now that we are using Spring Security, It should also declare
applicationContext-security-ns.xml (Spring config file for Spring Security).
The resulting block will look like this:
+------------------------------------------------------
@ -82,35 +91,39 @@ copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WE
+------------------------------------------------------
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:
To make it easier to experiment with the application, users should be able to log out of the application.
Edit %spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown:
+------------------------------------------------------
<table style="width:100%">
<tr>
<td><a href="<c:url value="/welcome.htm"/>">Home</a></td>
<td><a href="<c:url value="/j_spring_security_logout"/>">Logout</a></td>
<td style="text-align:right;color:silver">PetClinic :: a Spring Framework demonstration</td>
</tr>
<table class="footer">
<tr>
<td><a href="<c:url value="/welcome.do"/>">Home</a></td>
<td style="text-align:right;color:silver">PetClinic :: a Spring Framework demonstration</td>
<td align="right"><img src="<c:url value="/images/springsource-logo.png"/>"/></td>
<td align="right"><a href="<c:url value="/j_spring_security_logout"/>">Logout</a></td>
</tr>
</table>
+------------------------------------------------------
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:
+------------------------------------------------------
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
</value>
</property>
Our last step is to specify which URLs require authorization and which do not. Let's
edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-security-ns.xml.
All URLs ending with '.do' will be protected.
+------------------------------------------------------
<http auto-config="true">
<intercept-url pattern="/*.do" access="ROLE_USER" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>
+------------------------------------------------------
* Start Petclinic's database
Start the Hypersonic server (this is just normal Petclinic configuration):
@ -124,7 +137,7 @@ server
+------------------------------------------------------
cd %spring%\samples\petclinic
build setupDB
ant setupDB
+------------------------------------------------------
* Build and deploy the Petclinic WAR file
@ -141,53 +154,39 @@ copy dist\petclinic.war %TOMCAT_HOME%\webapps
Finally, start your container and try to visit the home page.
Your request should be intercepted and you will be forced to login.</p>
* Optional Bonus: Securing the Middle Tier
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.
In %spring%\samples\petclinic\war\WEB-INF\applicationContext-jdbc.xml, locate
the TransactionProxyFactoryBean definition. Add an additional property after
the existing "preInterceptors" property:
+------------------------------------------------------
<property name="postInterceptors" ref="methodSecurityInterceptor"/>
+------------------------------------------------------
Finally, we need to add in the referred-to "methodSecurityInterceptor" bean definition.
So pop an extra bean definition in, as shown below:
Finally, we need to declare a protect-pointcut that will hold the security restriction.
Inside %spring%\samples\petclinic\war\WEB-INF\applicationContext-security-ns.xml, update
the global-method-security tag as follows:
+------------------------------------------------------
<bean id="methodSecurityInterceptor" class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref bean="authenticationManager"/>
<property name="accessDecisionManager">
<bean class="org.springframework.security.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.vote.RoleVoter"/>
<bean class="org.springframework.security.vote.AuthenticatedVoter"/>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED
org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR
</value>
</property>
</bean>
<global-method-security secured-annotations="enabled">
<protect-pointcut expression="execution(* org.springframework.samples.petclinic.Clinic.storeVisit(..))" access="ROLE_SUPERVISOR"/>
</global-method-security>
+------------------------------------------------------
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 "rod", 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.
servlet container.
Login as "peter" that does not have the "ROLE_SUPERVISOR" role.
- Click on "Find owners"
- Keep the "last name" field blank and validate
- Select one owner in the list
- Click on "add visit"
- Add a description and validate
Access should be denied.
Now log out and try "rod", who has ROLE_SUPERVISOR. It should be working.
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. Spring Security provides a tag library to help
@ -195,27 +194,27 @@ copy dist\petclinic.war %TOMCAT_HOME%\webapps
the following line to the top of the file:
+------------------------------------------------------
<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
+------------------------------------------------------
Next, scroll down and find the link to "add visit". Modify it as follows:
+------------------------------------------------------
<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
<form method=GET action="<c:url value="/addVisit.htm"/>" name="formVisitPet<c:out value="${pet.id}"/>">
<input type="hidden" name="petId" value="<c:out value="${pet.id}"/>"/>
<input type="submit" value="Add Visit"/>
<sec:authorize ifAllGranted="ROLE_SUPERVISOR">
<form method="GET" action="<c:url value="/addVisit.do"/>" name="formVisitPet${pet.id}">
<input type="hidden" name="petId" value="${pet.id}"/>
<p class="submit"><input type="submit" value="Add Visit"/></p>
</form>
</authz:authorize>
</sec:authorize>
+------------------------------------------------------
* What now?
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
that you visit {{http://acegisecurity.org}}
and in particular review the "Suggested Steps" for getting started with Spring
Security. The suggested steps are optimized for learning Spring 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>
for each step so you can plan your integration activities.