Spring MVC
&
Spring Security
Craig Walls
About you...
• By show of hands...
• Java 6? Java 5? Java 1.4? Java 1.3? Java 1.2-?
• C#? Ruby? Groovy? Scala? Erlang? Python?
• Spring 1.x? Spring 2.0.x? Spring 2.5.x?
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
About me...
• Professionally developing software for almost 14
years
• Java developer for most of that time
• Telecom, finance, retail, education, software
• Now at Semantra, Inc. developing natural language
business intelligence solution
• Author of Spring in Action and XDoclet in Action
• Spring fanatic
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Agenda
• Spring MVC
• Review of Spring MVC pre-2.5
• What’s new in Spring 2.5’s MVC framework
• Spring Security
• Review of Acegi Security 1.0.x
• Introducing Spring Security 2.0
• Summary
• Q&A
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC
The “Other” Web Framework
Why Spring MVC?
• Spring was first released in June 2003
• 1.0 final in March 2004
• MVC choices were slim
• At the time, Struts led the pack
• WebWork was the next best choice
• Spring could do it better
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC vs. Struts
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC vs. Struts
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
DispatcherServlet
In WEB-INF/web.xml:
<servlet>
<servlet-name>roadrantz</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>roadrantz</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring’s Controllers
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
A Very Basic Controller
public class HomePageController extends AbstractController {
protected ModelAndView handleRequestInternal(
HttpServletRequest request, HttpServletResponse response)
throws Exception {
List recentRants = rantService.getRecentRants();
return new ModelAndView("home", "rants", recentRants);
}
private RantService rantService;
public void setRantService(RantService rantService) {
this.rantService = rantService;
}
}
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Command Controller
public class RantsForVehicleController extends AbstractCommandController {
public RantsForVehicleController() {
setCommandClass(Vehicle.class);
setCommandName("vehicle");
}
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command,
BindException errors) throws Exception {
Vehicle vehicle = (Vehicle) command;
Map model = errors.getModel();
model.put("rants", rantService.getRantsForVehicle(vehicle));
model.put("vehicle", vehicle);
return new ModelAndView("rantsForVehicle", model);
}
private RantService rantService;
public void setRantService(RantService rantService) {
this.rantService = rantService;
}
}
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Form Controller
public class AddRantFormController extends SimpleFormController {
private static final String[] ALL_STATES = { "AL", "AK", ... };
public AddRantFormController() {
setCommandClass(Rant.class);
setCommandName("rant");
}
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
Rant rantForm = (Rant) super.formBackingObject(request);
rantForm.setVehicle(new Vehicle());
return rantForm;
}
protected Map referenceData(HttpServletRequest request) throws Exception {
Map referenceData = new HashMap();
referenceData.put("states", ALL_STATES);
return referenceData;
}
protected ModelAndView onSubmit(Object command, BindException bindException)
throws Exception {
Rant rant = (Rant) command;
rantService.addRant(rant);
return new ModelAndView(getSuccessView());
}
private RantService rantService;
public void setRantService(RantService rantService) {
this.rantService = rantService;
}
}
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Configuring Controllers
In WEB-INF/roadrantz-servlet.xml:
<bean id="homePageController"
class="com.roadrantz.mvc.HomePageController">
<property name="rantService" ref="rantService" />
</bean>
<bean id="rantsForVehicleController"
class="com.roadrantz.mvc.RantsForVehicleController">
<property name="rantService" ref="rantService" />
</bean>
<bean id="addRantController"
class="com.roadrantz.mvc.AddRantFormController">
<property name="formView" value="addRant" />
<property name="successView" value="rantAdded" />
<property name="rantService" ref="rantService" />
</bean>
<bean id="loginController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
Response
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Follow That Request
Request
Response
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Handler Mappings
• Map requested URL patterns to controllers
• Comes in 5 flavors:
• BeanNameUrlHandlerMapping
• CommonsPathMapHandlerMapping
• ControllerClassNameHandlerMapping
• DefaultAnnotationHandlerMapping
• SimpleUrlHandlerMapping
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
SimpleUrlHandlerMapping
In WEB-INF/roadrantz-servlet.xml:
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/login.htm=loginController
/home.htm=homePageController
/rantsForVehicle.htm=rantsForVehicleController
/addRant.htm=addRantController
</value>
</property>
</bean>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
ControllerClassNameHandlerMapping
In WEB-INF/roadrantz-servlet.xml:
<bean id="urlMapping"
class="org.springframework.web.servlet.mvc.support.
ControllerClassNameHandlerMapping" />
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
View Resolvers
• Map logical view names in ModelAndView to actual
view implementation (ex. a JSP file)
• Come in 9 flavors:
• BeanNameViewResolver
• FreeMarkerViewResolver
• InternalResourceViewResolver
• JasperReportsViewResolver
• ResourceBundleViewResolver
• VelocityLayoutViewResolver
• VelocityViewResolver
• XmlViewResolver
• XsltViewResolver
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
InternalResourceViewResolver
In WEB-INF/roadrantz-servlet.xml:
<bean class="org.springframework.web.servlet.view.
InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring JSP Tag Libraries
• Two tag libraries:
• General purpose
• Form-bindin
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
JSP Tag Libraries
In WEB-INF/roadrantz-servlet.xml:
<%@ page contentType="text/html" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="rr" tagdir="/WEB-INF/tags" %>
<html>
<body>
<h2>Enter a rant...</h2>
<form:form method="POST" action="addRant.htm" commandName="rant">
<b><spring:message code="field.state" /></b>
<rr:stateSelection path="vehicle.state" />
<form:errors path="vehicle.state" cssClass="error"/><br>
<b><spring:message code="field.plateNumber" /></b>
<form:input path="vehicle.plateNumber" />
<form:errors path="vehicle.plateNumber" cssClass="error"/><br>
<b><spring:message code="field.rantText" /></b>
<form:errors path="rantText" cssClass="error"/><br>
<form:textarea path="rantText" rows="5" cols="50" />
<input type="submit"/>
</form:form>
</body>
</html>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC Summary
• DispatcherServlet is front controller
• Handler mappings maps URLs to controllers
• Controllers process requests
• Returning results and logical view name in
ModelAndView
• View resolvers map logical view names to actual
views
• Two tag libraries
• Form-binding and general-purpose
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
And then there’s 2.5
• Annotation-driven
• Much less XML
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC 2.5 XML
In WEB-INF/roadrantz-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.roadrantz.mvc" />
<bean class="org.springframework.web.servlet.mvc.annotation.
DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
<context:component-scan>
• Scans all beans in a package and sub-packages
• Automatically registers beans from classes that are
annotated with certain stereotype annotations
• @Aspect
• @Component
• @Controller
• @Repository
• @Service
• Automatically autowires any properties, method
parameters, or constructor args that are annotated with
@Autowired
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
DefaultAnnotationHandlerMapping
• Maps request URLs to controllers based on
@RequestMapping annotation
• @RequestMapping can be placed at class-level or
at method-level
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Revisiting the Controller
@Controller
@RequestMapping("/home.htm")
public class HomePageController {
@RequestMapping(method = RequestMethod.GET)
public String showHomePage(ModelMap model) {
model.addAttribute(rantService.getRecentRants());
return "home";
}
@Autowired
RantService rantService;
}
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
A Form Controller ?
@Controller
@RequestMapping("/addRant.htm")
public class AddRantFormController {
@RequestMapping(method = RequestMethod.GET)
public String setupForm(ModelMap model) {
return "addRant";
}
@ModelAttribute("rant")
public Rant setupRant() {
Rant rant = new Rant();
rant.setVehicle(new Vehicle());
return rant;
}
@ModelAttribute("states")
public String[] getAllStates() { return WebConstants.ALL_STATES;}
@RequestMapping(method = RequestMethod.POST)
protected String addRant(@ModelAttribute("rant")
Rant rant) {
rantService.addRant(rant);
return "rantAdded";
}
@Autowired
RantService rantService;
}
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring MVC 2.5 Summary
• <context:component-scan> lets you skip writing
XML to configure controllers (and other stuff)
• DefaultAnnotationHandlerMapping lets you move
the URL mappings into the controllers themselves
• No more controller hierarchy...controllers are now
just annotated POJOs
• @Controller, @RequestMapping, @ModelAttribute
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring Security
Save the Fairies
Acegi Security for Spring
• Created by Ben Alex in 2003
• 1.0 in March 2004
• Applies security rules using Servlet Filters and
Spring AOP
• Extremely powerful and flexible
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
What Acegi Offers
• Declarative Security
• Keeps security details out of your code
• Authentication and Authorization
• Against virtually any user store
• Support for anonymous sessions, concurrent
sessions, remember-me, channel-enforcement, and
much more
• Spring-based, but can be used for non-Spring web
frameworks
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
The Downside of Acegi
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Acegi Guilty of Fairycide?
“Every time you use Acegi...A fairy dies.”
- Daniel Deiphouse
http://netzooid.com/blog/2007/12/03/every-time-you-use-acegi/
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Acegi’s Filter Proxy
In WEB-INF/web.xml:
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Filter Proxy
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Example Acegi Config
<?xml version="1.0" encoding="UTF-8"?> </property>
<beans xmlns="http://www.springframework.org/schema/beans" </bean>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <bean id="httpSessionIntegrationFilter"
xsi:schemaLocation="http://www.springframework.org/schema/beans class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <property name="forceEagerSessionCreation" value="true" />
<bean id="filterChainProxy" </bean>
class="org.acegisecurity.util.FilterChainProxy"> <bean id="filterSecurityInterceptor"
<property name="filterInvocationDefinitionSource"> class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<value> <property name="authenticationManager" ref="authenticationManager" />
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON <property name="accessDecisionManager" ref="accessDecisionManager" />
PATTERN_TYPE_APACHE_ANT <property name="objectDefinitionSource">
/**=channelProcessingFilter,httpSessionIntegrationFilter, <value>
logoutFilter,authenticationProcessingFilter,rememberMeProcessingFilter, CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor PATTERN_TYPE_APACHE_ANT
</value> /booger.htm=ROLE_BOOGER
</property> </value>
</bean> </property>
<bean id="authenticationProcessingFilter" </bean>
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <bean id="anonymousProcessingFilter"
<property name="authenticationManager" ref="authenticationManager"/> class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="authenticationFailureUrl" value="/login.htm?login_error=1" /> <property name="key" value="foobar" />
<property name="defaultTargetUrl" value="/" /> <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS" />
<property name="filterProcessesUrl" value="/j_acegi_security_check" /> </bean>
<property name="rememberMeServices" ref="rememberMeServices" /> <bean id="anonymousAuthenticationProvider"
</bean> class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<bean id="authenticationManager" <property name="key" value="foobar" />
class="org.acegisecurity.providers.ProviderManager"> </bean>
<property name="providers"> ! <bean id="rememberMeProcessingFilter"
<list> ! class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<ref bean="daoAuthenticationProvider" /> ! <property name="rememberMeServices" ref="rememberMeServices" />
<ref bean="anonymousAuthenticationProvider" /> ! <property name="authenticationManager" ref="authenticationManager" />
<ref bean="rememberMeAuthenticationProvider" /> ! </bean>
</list> ! <bean id="rememberMeServices"
</property> ! class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
</bean> ! <property name="userDetailsService" ref="userDetailsService" />
<bean id="daoAuthenticationProvider" ! <property name="key" value="roadRantz" />
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> ! </bean>
<property name="userDetailsService" ! <bean id="rememberMeAuthenticationProvider"
ref="userDetailsService" /> ! class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
</bean> ! <property name="key" value="roadRantz" />
<bean id="userDetailsService" ! </bean>
class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"> <bean id="logoutFilter"
<property name="dataSource" ref="dataSource" /> class="org.acegisecurity.ui.logout.LogoutFilter">
<property name="usersByUsernameQuery" <constructor-arg value="/home.htm" />
value="SELECT email as username, password, 'true' FROM Motorist WHERE email=?" /> <constructor-arg>
<property name="authoritiesByUsernameQuery" <list>
value="SELECT email as username, privilege FROM Motorist_Privileges mp, Motorist m WHERE <ref bean="rememberMeServices"/>
mp.motorist_id = m.id AND m.email=?" /> <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</bean> </list>
<bean id="authenticationEntryPoint" </constructor-arg>
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> </bean>
<property name="loginFormUrl" value="/login.htm" /> <bean id="channelProcessingFilter"
<property name="forceHttps" value="true" /> class="org.acegisecurity.securechannel.ChannelProcessingFilter">
</bean> <property name="channelDecisionManager" ref="channelDecisionManager" />
<bean id="accessDecisionManager" <property name="filterInvocationDefinitionSource">
class="org.acegisecurity.vote.UnanimousBased"> <value>
<property name="allowIfAllAbstainDecisions" value="false" /> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
<property name="decisionVoters"> PATTERN_TYPE_APACHE_ANT
<list> /login.htm=REQUIRES_SECURE_CHANNEL
<bean class="org.acegisecurity.vote.RoleVoter" /> /j_acegi_security_check*=REQUIRES_SECURE_CHANNEL
</list> /**=REQUIRES_INSECURE_CHANNEL
</property> </value>
</bean> </property>
<bean id="exceptionTranslationFilter" </bean>
class="org.acegisecurity.ui.ExceptionTranslationFilter"> </beans>
<property name="authenticationEntryPoint"
ref="authenticationEntryPoint" />
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error.htm" />
</bean>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
What was in that XML?
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Acegi’s Moving Parts
• Security Interceptor - Determines what resources are to
be secured--and how they are to be secured
• Filters - Intercept requests and apply various aspects of
security
• Authentication, Remember-me, Concurrent sessions, Anonymous, Logout, Channel-
processing, Integration, etc
• Authentication Manager - Determines who the user is and
what authorities they are granted
• Authentication Providers - Used by the authentication manager to retrieve user
information. Includes DAO-based, anonymous, and remember-me providers
• Authorization Manager - Allows/Disallows access to a
resource, givena user’s granted authorities and a
resource’s required authorization
• Usually defers to one or more access decision voters to help decide
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring Security 2.0
• All the same goodness of Acegi...and more
• Exploits custom Spring configuration namespaces
(ala Spring 2.0)
• Acegi’s complex configuration details now hidden
behind simpler XML elements
• Offers auto-configuration
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Spring Security 2.0 Filter
In WEB-INF/web.xml:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Simpler Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<http auto-config="true">
<intercept-url pattern="/addRant.htm" access="ROLE_MOTORIST" />
<intercept-url pattern="/home.htm" requires-channel="http" />
<intercept-url pattern="/login.htm" requires-channel="https" />
<form-login login-page="/login.htm" />
</http>
<authentication-provider user-service-ref="userService" />
<jdbc-user-service id="userService" data-source-ref="dataSource" />
</beans:beans>
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
<http>:The Magic Element
• The central configuration element for web security
• <intercept-url> declares pages to be secured (and
how)
• <form-login> refers to a login page
• Other sub-elements provide support for HTTP Basic
authentication, Logout, Remember-Me, and
Anonymous sessions...or...
• “auto-config” does all of that for you!
• In fact, it can also automatically create a login form for you
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
<authentication-provider>
• Declares an authentication provider
• Refers to a user details service
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
<jdbc-user-service>
• Declares a JDBC-based user service
• Retrieves user information and authorization details from
a database table.
• Assumes “SELECT username,password,enabled FROM users WHERE
username=?” for user details.
• Assumes “SELECT username,authority FROM authorities WHERE username=?” for
authorization info.
• As of 2.0-m4, can’t override SQL. See and (please) vote for SEC-703.
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Summary
Is it over yet?
Spring MVC & Security
• Spring continues to evolve and improve
• This especially applies to Spring MVC and Spring
Security
• Spring MVC 2.5 has embraced annotations for
configuration, reducing the amount of XML required
• Spring Security 2.0 has dramatically decreased the
amount of XML required by employing security-specific
configuration elements
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Example Code & Slides
• RoadRantz example (from SiA) updated to use the
latest Spring goodness:
• svn://svn.geekisp.com/SiA/trunk/RoadRantz
• Updated to use Spring MVC 2.5, Spring Security
2.0 nightly build (with SEC-703 patch), and Spring
WebFlow 2.0-m4
• Work in progress--No guarantees
• These slides: http://www.habuma.com/spring/SpringMVCandSecurity.pdf
E-mail: craig@habuma.com Blog: http://www.springloaded.info Source Code: svn://svn.geekisp.com/SiA svn://svn.geekisp.com/habuma
Q&A
Time to Play Stump the Speaker