Getting Started with Spring Security 3.1
Rob Winch, Sr Software Engineer, Spring Security Lead @rob_winch
© 2012 SpringOne 2GX. All rights reserved. Do not distribute without permission.
About Me • • • •
2
Spring Security Lead at Spring Source / VMware 15+ years web experience 10+ years of Java experience Previous Employment – Health Care Security at Cerner (7 years) – Grid Computing at Argonne National Labs (1 year) – Proteomics Research at Loyola University Chicago (1 year) – Started professional career as PERL contractor in High School
Agenda • • • •
What is Spring Security Setting up Spring Security How the basic Spring Security flow works Simple customizations of Spring Security – Page – Custom Controller • Global Method Security • Q&A
3
Tell me about Spring Security • Formerly known as Acegi Security • Authentication – Database, LDAP, CAS, OpenID, Pre-Authentication, custom, etc • Authorization – URL based, Method Based (AOP) • Extensions • Simple yet powerful
4
Java Servlet Filter Review - Dispatcher web.xml
filter1
Filter1
filter1
/*
5
Java Servlet Filter Review - Dispatcher Filter1.java public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse ServletResponse response, response, FilterChain FilterChain filterChain) filterChain) …… {{ …… // // do do something something before before System.out.println("> System.out.println("> "" ++ requestUrl); requestUrl); // run rest of application // run rest of application filterChain.doFilter(request, filterChain.doFilter(request, response); response); // cleanup // cleanup System.out.println("< System.out.println("< "" ++ requestUrl); requestUrl); }}
6
Java Servlet Filter Review - Dispatcher HTTP GET /home
7
Request Processing
STDOUT
Java Servlet Filter Review - Dispatcher HTTP
Request Processing Filter1.doFilter(request, response, filterChain)
GET /home
8
STDOUT
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
9
Filter1
> /home
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
Filter1 filterChain.doFilter(request,response);
String url = "/WEB-INF/home.jsp"; request .getRequestDispatcher(url) .forward(request, response);
10
> /home
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
Filter1 filterChain.doFilter(request,response);
String url = "/WEB-INF/home.jsp"; request .getRequestDispatcher(url) .forward(request, response);
home.jsp
11
> /home
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
Filter1 filterChain.doFilter(request,response);
String url = "/WEB-INF/home.jsp"; request .getRequestDispatcher(url) .forward(request, response);
OK
12
home.jsp
> /home
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
Filter1 filterChain.doFilter(request,response);
String url = "/WEB-INF/home.jsp"; request .getRequestDispatcher(url) .forward(request, response);
OK
13
home.jsp
> /home
Java Servlet Filter Review - Dispatcher HTTP
Request Processing
STDOUT
Filter1.doFilter(request, response, filterChain)
GET /home
Filter1
> /home
filterChain.doFilter(request,response);
String url = "/WEB-INF/home.jsp"; request .getRequestDispatcher(url) .forward(request, response);
OK
home.jsp < /home
14
Java Servlet Filter Review - Dispatcher web.xml
filter1
filter1
Filter1
Filter1
filter1
filter1
/*
/*
REQUEST
REQUEST
FORWARD
FORWARD
15
Java Servlet Filter Review - Dispatcher HTTP GET /home
16
Request Processing
STDOUT
Java Servlet Filter Review - Dispatcher HTTP GET /home
17
Request Processing Filter1
STDOUT > /home
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1 request.getRequestDispatcher("/home.jsp") .forward(request, response);
18
STDOUT > /home
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1
19
> /home.jsp
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1 OK
20
home.jsp
> /home.jsp
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1 OK
21
home.jsp
> /home.jsp
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1 OK
> /home.jsp
home.jsp < /home.jsp
22
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1 OK
> /home.jsp
home.jsp < /home.jsp
23
Java Servlet Filter Review - Dispatcher HTTP GET /home
Request Processing Filter1
STDOUT > /home
request.getRequestDispatcher("/home.jsp") .forward(request, response);
Filter1 OK
> /home.jsp
home.jsp < /home.jsp < /home
24
Java Servlet Filter Review - Dispatcher • • • •
25
Spring Security is based on Servlet Filters Rare to process other dispatcher types, but important to be aware of them Ensure to include the necessary dispatcher elements Other possible dispatcher values include – REQUEST (default) – INCLUDE – FORWARD – ERROR
Java Servlet Filter Review - FilterChain public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse response, FilterChain ServletResponse response, FilterChain filterChain) filterChain) …… {{ // // run run rest rest of of application application filterChain.doFilter(request, filterChain.doFilter(request, response); response);
}}
26
Java Servlet Filter Review - FilterChain public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse response, FilterChain ServletResponse response, FilterChain filterChain) filterChain) …… {{ // // run run rest rest of of application application filterChain.doFilter(request, filterChain.doFilter(request, response); response); securityFilter.doFilter(request, securityFilter.doFilter(request, response, response, filterChain); filterChain);
}} 27
Java Servlet Filter Review - FilterChain public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse response, FilterChain ServletResponse response, FilterChain filterChain) filterChain) …… {{ // // run run rest rest of of application application filterChain.doFilter(request, filterChain.doFilter(request, response); response); securityFilter.doFilter(request, securityFilter.doFilter(request, response, response, filterChain); filterChain); servlet.service(request, response); servlet.service(request, response);
}} 28
Java Servlet Filter Review - FilterChain public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse response, FilterChain ServletResponse response, FilterChain filterChain) filterChain) …… {{ try try {{ // // run run rest rest of of application application filterChain.doFilter(request, filterChain.doFilter(request, response); response); securityFilter.doFilter(request, securityFilter.doFilter(request, response, response, filterChain); filterChain); servlet.service(request, response); servlet.service(request, response); }} catch catch (SecurityException (SecurityException e) e) {{ // // handle handle error error by by sending sending to to page page }} finally finally {{ // // cleanup cleanup }} }} 29
Demo Messages Application
30
Setting up Spring Security
31
Basic Spring Security Setup • Add Spring Security Dependencies • Update web.xml • Create Spring Security Configuration
32
Specifying Dependencies with Maven <dependencies> <dependencies> ... ... <dependency> <dependency>
org.springframework.security
org.springframework.security
<artifactId>spring-security-core <artifactId>spring-security-core
3.1.3.RELEASE
3.1.3.RELEASE
<dependency> <dependency>
org.springframework.security
org.springframework.security
<artifactId>spring-security-web <artifactId>spring-security-web
3.1.3.RELEASE
3.1.3.RELEASE
<dependency> <dependency>
org.springframework.security
org.springframework.security
<artifactId>spring-security-config <artifactId>spring-security-config
3.1.3.RELEASE
3.1.3.RELEASE
33
Specifying Dependencies with Gradle
dependencies dependencies {{ compile compile "org.springframework:spring-context:$springVersion", "org.springframework:spring-context:$springVersion", ... ... "org.springframework.security:spring-security-web:3.1.3.RELEASE", "org.springframework.security:spring-security-web:3.1.3.RELEASE", "org.springframework.security:spring-security-config:3.1.3.RELEASE", "org.springframework.security:spring-security-config:3.1.3.RELEASE", "org.springframework.security:spring-security-core:3.1.3.RELEASE" "org.springframework.security:spring-security-core:3.1.3.RELEASE" }}
34
Update web.xml - ContextLoaderListener web.xml
<param-name>contextConfigLocation <param-name>contextConfigLocation <param-value> <param-value> /WEB-INF/spring/*.xml /WEB-INF/spring/*.xml
<listener> <listener> <listener-class> <listener-class> org.springframework.web.context.ContextLoaderListener org.springframework.web.context.ContextLoaderListener
35
What is the ContextLoaderListener • Not Specific to Spring Security • Creates a Spring ApplicationContext using the Spring Configurations (i.e. the value of contextConfigLocation) • Can be used to lookup objects in ApplicationContext • Rare to interact with ApplicationContext directly
36
ContextLoaderListener pseudocode // // init init ApplicationContext ApplicationContext XmlWebApplicationContext XmlWebApplicationContext applicationContext applicationContext == new new XmlWebApplicationContext(); XmlWebApplicationContext(); applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); applicationContext.refresh(); applicationContext.refresh(); // // Use Use ApplicationContext ApplicationContext Filter Filter filter filter == applicationContext.getBean("springSecurityFilterChain", applicationContext.getBean("springSecurityFilterChain", Filter.class); Filter.class);
37
ContextLoaderListener pseudocode // // init init ApplicationContext ApplicationContext XmlWebApplicationContext XmlWebApplicationContext applicationContext applicationContext == new new XmlWebApplicationContext(); XmlWebApplicationContext(); "/WEB-INF/spring/*.xml" applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); "/WEB-INF/spring/*.xml" applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); applicationContext.refresh(); applicationContext.refresh();
// Use ApplicationContext // Use ApplicationContext <param-name>contextConfigLocation <param-name>contextConfigLocation Filter filter = Filter filter = <param-value> <param-value> applicationContext.getBean("springSecurityFilterChain", applicationContext.getBean("springSecurityFilterChain", /WEB-INF/spring/*.xml /WEB-INF/spring/*.xml Filter.class); Filter.class);
38
ContextLoaderListener pseudocode // // init init ApplicationContext ApplicationContext XmlWebApplicationContext XmlWebApplicationContext applicationContext applicationContext == new new XmlWebApplicationContext(); XmlWebApplicationContext(); applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); applicationContext.setConfigLocation("/WEB-INF/spring/*.xml"); applicationContext.refresh(); applicationContext.refresh(); // // Use Use ApplicationContext ApplicationContext Filter Filter filter filter == applicationContext.getBean("springSecurityFilterChain", applicationContext.getBean("springSecurityFilterChain", Filter.class); Filter.class);
39
Update web.xml - springSecurityFilterChain web.xml
springSecurityFilterChain
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
springSecurityFilterChain
/*
/*
40
DelegatingFilterProxy pseudocode public public class class DelegatingFilterProxy DelegatingFilterProxy implements implements Filter Filter {{ public public void void init(FilterConfig init(FilterConfig config) config) throws throws ServletException ServletException {{ // // applicationContext applicationContext is is obtained obtained from from ContextLoaderListener ContextLoaderListener this.delegate this.delegate == applicationContext.getBean("springSecurityFilterChain", applicationContext.getBean("springSecurityFilterChain", Filter.class); Filter.class); }} public public void void doFilter(...) doFilter(...) throws throws ... ... {{ this.delegate.doFilter(request, this.delegate.doFilter(request, response, response, filterChain); filterChain); }} public public void void destroy() destroy() {{ // // this this may may not not be be invoked invoked depending depending on on the the settings settings this.delegate.destroy(); this.delegate.destroy(); }} private private Filter Filter delegate; delegate; }} 41
DelegatingFilterProxy pseudocode public public class class DelegatingFilterProxy DelegatingFilterProxy implements implements Filter Filter {{ public public void void init(FilterConfig init(FilterConfig config) config) throws throws ServletException ServletException {{ // // applicationContext applicationContext is is obtained obtained from from ContextLoaderListener ContextLoaderListener this.delegate = this.delegate = springSecurityFilterChain applicationContext.getBean("springSecurityFilterChain", springSecurityFilterChain applicationContext.getBean("springSecurityFilterChain", Filter.class); Filter.class); }}
public void public void doFilter(...) doFilter(...) throws throws ... ... {{
springSecurityFilterChain
springSecurityFilterChain
this.delegate.doFilter(request, response, this.delegate.doFilter(request, response, filterChain); filterChain);
/*
}}
/*
public void public void destroy() destroy() {{ // // this this may may not not be be invoked invoked depending depending on on the the settings settings this.delegate.destroy(); this.delegate.destroy(); }} private private Filter Filter delegate; delegate; }} 42
DelegatingFilterProxy pseudocode public public class class DelegatingFilterProxy DelegatingFilterProxy implements implements Filter Filter {{ public public void void init(FilterConfig init(FilterConfig config) config) throws throws ServletException ServletException {{ // // applicationContext applicationContext is is obtained obtained from from ContextLoaderListener ContextLoaderListener this.delegate this.delegate == applicationContext.getBean("springSecurityFilterChain", applicationContext.getBean("springSecurityFilterChain", Filter.class); Filter.class); }} public public void void doFilter(...) doFilter(...) throws throws ... ... {{ this.delegate.doFilter(request, this.delegate.doFilter(request, response, response, filterChain); filterChain); }} public public void void destroy() destroy() {{ // // this this may may not not be be invoked invoked depending depending on on the the settings settings this.delegate.destroy(); this.delegate.destroy(); }} private private Filter Filter delegate; delegate; }} 43
Create security.xml • The file location should be src/main/webapp/WEB-INF/spring/security.xml to match the contextConfigLocation • Need to ensure to get the xml namespace declaration correct • Spring Tool Suite (STS) can help with adding namespace decloarations
44
Create security.xml with Spring Tool Suite • • • • • •
45
In STS right click src/main/webapp/WEB-INF/spring/ New → Spring Bean Configuration File Enter security.xml as the file name Click Next Select Security Click Finish
src/main/webapp/WEB-INF/security.xml Add the following between the
tags <security:http <security:http use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:form- <security:form- /> /> <security:authentication-manager> <security:authentication-manager> <security:authentication-provider> <security:authentication-provider> <security:-service> <security:-service> <security: <security: name="" name="" ="" ="" authorities="ROLE_"/> authorities="ROLE_"/> 46
Demo Basic Spring Security
47
FilterChainProxy (springSecurityFilterChain) Pseudocode public public void void doFilter(ServletRequest doFilter(ServletRequest request, request, ServletResponse response, FilterChain ServletResponse response, FilterChain filterChain) filterChain) …… {{ Filter[] Filter[] delegates delegates == lookupDelegates(request); lookupDelegates(request); for(Filter delegate : for(Filter delegate : delegates) delegates) {{ delegate.doFilter(request, delegate.doFilter(request, response, response, chain); chain);
}} }}
if(delegate if(delegate does does not not invoke invoke filterChain.doFilter) filterChain.doFilter) return; return;
filterChain.doFilter(request, filterChain.doFilter(request, response); response);
48
Unauthenticated Request to Protected Resource HTTP GET /messages/
49
Request Processing
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
50
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter
51
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
try { filterChain.doFilter(...); }catch(AccessDeniedException e){ }
Exception TranslationFilter
52
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 53
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern=" <security:intercept-url pattern="/**" <security:intercept-urlpattern="/**" pattern="/** /**"" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception ... ...
TranslationFilter Security FilterInterceptor
54
Does / match /**
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 55
Yes, so the current must have ROLE_
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 56
Not logged in so throw AccessDenied Exception
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 57
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
Exception TranslationFilter Security FilterInterceptor 58
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
302 /spring_security_
Exception TranslationFilter Security FilterInterceptor
59
Ant Patterns Spring Security uses an AntPathRequestMatcher to determine if a URL matches the current URL. The following rules are used when matching: • • • • •
60
Query parameters are not included in the match The context path is not included in the match ? matches one character * matches zero or more characters (not a directory delimiter i.e. /) ** matches zero or more 'directories' in a path
Ant Patterns - Examples Ant Pattern examples that assume a context path of /messages Pattern
Description
/**
Matches any URL
/*
Matches anything in root folder
Full Path
Path to Match
/messages/1
/1
/messages/2?a=b /2 /messages/1/
61
/1/
Ant Patterns - Examples Ant Pattern examples that assume a context path of /messages Pattern
Description
Full Path
Path to Match
/1/**
Matches anything that starts with /1
/messages/1
/1
/messages/1?a=b
/1
/messages/1/
/1/
/messages/1/view
/1/view
/messages/other/
/other/
/messages/2/view
/2/view
62
Ant Patterns - Examples Be careful when using pattern matching Pattern
Description
Full Path
Path to Match
/**/*.css
Matches anything that ends with .css
/messages/styles/main.css
/styles/main.css
/messages/1
/1
/messages/1.css
/1.css
63
Ant Patterns • The less restrictive the mapping the easier it is for a malicious to by • Spring MVC will treat /1.css the same as /1, so a malicious can use this to by security constraints • Other ways to by URL based security (i.e. path variables, non-normalized URLs, etc). Spring Security does have things in place to help protect you (i.e. HttpFirewall) • Best to combine URL Security with Method Security to provide defense in depth
64
Requesting page HTTP GET /messages/spring_security_
65
Request Processing
Requesting page HTTP GET /messages/spring_security_
Request Processing Delegating FilterProxy Filter ChainProxy
66
Requesting page HTTP GET /messages/spring_security_
Request Processing Delegating FilterProxy Filter ChainProxy
DefaultPage GeneratingFilter
67
Requesting page HTTP GET /messages/spring_security_
Request Processing Delegating FilterProxy Filter ChainProxy
DefaultPage GeneratingFilter
68
Requesting page HTTP GET /messages/spring_security_
Request Processing Delegating FilterProxy Filter ChainProxy
DefaultPage GeneratingFilter
69
Generate a page for requests to /spring_security_
Requesting page HTTP GET /messages/spring_security_
Request Processing Delegating FilterProxy Filter ChainProxy
200 Page
70
DefaultPage GeneratingFilter
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing HttpSession
Security ContextHolde r
71
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
72
HttpSession
Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
HttpSession
Security ContextHolde r
HttpSession no Authentication 73
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy
name AuthenticationFilter
74
HttpSession
Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy
HttpSession
Filter ChainProxy
Security ContextHolde r
name AuthenticationFilter /secret 75
Authentication Manager
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy
HttpSession
Filter ChainProxy
Security ContextHolde r
name AuthenticationFilter
/secret 76
Authentication Manager
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy
HttpSession
Filter ChainProxy
Security ContextHolde r
name AuthenticationFilter /secret 77
Authentication Manager
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy
name AuthenticationFilter
78
HttpSession
Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
302 Saved Request
79
Request Processing Delegating FilterProxy Filter ChainProxy
name AuthenticationFilter
HttpSession
Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
HttpSession
Security ContextHolde r SecurityContext was updated save to HttpSession
80
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
81
HttpSession
Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
82
HttpSession Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
83
HttpSession Security ContextHolde r
Authenticating via name & HTTP POST /messages/j_spring_security_check j_name= j_=security
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
84
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing HttpSession Security ContextHolde r
85
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy
86
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
87
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
HttpSession Security ContextHolde r
Update SecurityContext Holder 88
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
89
HttpSession
Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy
HttpSession
Filter ChainProxy SecurityContext PersistenceFilter
90
Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
91
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
92
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy RequestCache AwareFilter
HttpSession Security ContextHolde r
filterChain.doFilter(savedRequest, response)
93
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy
SecurityFilter Interceptor
94
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy
SecurityFilter Interceptor
95
HttpSession Security ContextHolde r Current has ROLE_ Grant Access
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy
SecurityFilter Interceptor
96
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
HttpSession Security ContextHolde r
SecurityContext has not changed; no update to session 97
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
HttpSession Security ContextHolde r
Clear SecurityContextHolder 98
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
99
HttpSession Security ContextHolde r
Requesting Protected Resource while Authenticated HTTP Saved Request
Request Processing Delegating FilterProxy Filter ChainProxy SecurityContext PersistenceFilter
100
HttpSession Security ContextHolde r
Spring Security Filters • Each Filter has a specific task • Each Filter acts as a controller • Logic in Filter's can be implemented in a controller of the framework of your choice
101
Custom Page
102
src/main/webapp/WEB-INF/security.xml <security:http <security:http use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:form- <security:form- -page="/" -page="/" authentication-failure-url="/?error"/> authentication-failure-url="/?error"/>
103
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
104
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter
105
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
try { filterChain.doFilter(...); }catch(AccessDeniedException e){ }
Exception TranslationFilter
106
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 107
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern=" <security:intercept-url pattern="/**" <security:intercept-urlpattern="/**" pattern="/** /**"" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception ... ...
TranslationFilter Security FilterInterceptor
108
Does / match /**
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 109
Yes, so the current must have ROLE_
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 110
Not logged in so throw AccessDenied Exception
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 111
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
Exception TranslationFilter Security FilterInterceptor 112
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
302 /
Exception TranslationFilter Security FilterInterceptor
113
Unauthenticated Request to Protected Resource HTTP GET /messages/
114
Request Processing
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
115
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter
116
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
try { filterChain.doFilter(...); }catch(AccessDeniedException e){ }
Exception TranslationFilter
117
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 118
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern=" <security:intercept-url pattern="/**" <security:intercept-urlpattern="/**" pattern="/** /**"" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception ... ...
TranslationFilter Security FilterInterceptor
119
Does / match /**
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 120
Yes, so the current must have ROLE_
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
<security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> Exception access="hasRole('ROLE_')"/> ... ... TranslationFilter
Security FilterInterceptor 121
Not logged in so throw AccessDenied Exception
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
Exception TranslationFilter Security FilterInterceptor 122
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
Exception TranslationFilter Security FilterInterceptor 123
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
catch(AccessDeniedException e){ // save HTTP request with RequestCache // send to page w/ // AuthenticationEntryPoint
}
302 /
Exception TranslationFilter Security FilterInterceptor
124
src/main/webapp/WEB-INF/security.xml <security:http use-expressions="true"> <security:intercept-url pattern="/" access="permitAll"/> <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> <security:form- -page="/" authentication-failure-url="/?error"/>
125
src/main/webapp/WEB-INF/views/.jspx
126
Multiple
127
Unauthenticated Request to Protected Resource HTTP GET /messages/resources/main.css
Request Processing Delegating FilterProxy Filter ChainProxy
128
Unauthenticated Request to Protected Resource HTTP
Request Processing
GET Delegating /messages/resources/main.css FilterProxy <security:http <security:http security="none" security="none" pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
129
Unauthenticated Request to Protected Resource HTTP
Request Processing
GET Delegating /messages/resources/main.css FilterProxy <security:http <security:http security="none" security="none" pattern="/resources/**"/> pattern=" /resources/** pattern="/resources/**"/> pattern=" /resources/**""Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
Exception TranslationFilter
130
Does /resources/main.css match /resources/**
Unauthenticated Request to Protected Resource HTTP
Request Processing
GET Delegating /messages/resources/main.css FilterProxy <security:http <security:http security="none" security="none" pattern="/resources/**"/> pattern=" /resources/** pattern="/resources/**"/> pattern=" /resources/**""Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
Exception TranslationFilter
131
Yes, so security is disabled
Unauthenticated Request to Protected Resource HTTP GET /messages/resources/main.css
Request Processing Delegating FilterProxy Filter ChainProxy
132
Unauthenticated Request to Protected Resource HTTP GET /messages/
Request Processing Delegating FilterProxy Filter ChainProxy
133
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
134
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern=" /resources/** pattern="/resources/**"/> pattern=" /resources/**""Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
Exception TranslationFilter
135
Does / match /resources/**
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
136
No, so next
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
137
Does / match /** (default pattern)
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
138
Yes, so select this
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url pattern="/**" /** <security:intercept-urlpattern=" pattern="/**" pattern=" /**"" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ... Exception TranslationFilter
139
Does / match /**
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"/> pattern="/resources/**"/>
Filter Filter <security:http <security:http auto-config="true" auto-config="true" ChainProxy ChainProxy use-expressions="true"> use-expressions="true"> <security:intercept-url <security:intercept-url pattern="/**" pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')" ... ... Exception TranslationFilter
140
Yes, so requires ROLE_
Unauthenticated Request to Protected Resource HTTP GET /messages/resources/main.css
Request Processing Delegating FilterProxy Filter ChainProxy
141
Unauthenticated Request to Protected Resource HTTP
Request Processing
GET Delegating /messages/resources/main.css FilterProxy <security:http <security:http security="none" security="none" pattern="/resources/**"> pattern="/resources/**">
Filter Filter <security:intercept-url <security:intercept-url ChainProxy ChainProxy pattern="/resources/.css" pattern="/resources/.css" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" Exception use-expressions="true"> use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
142
Unauthenticated Request to Protected Resource HTTP
Request Processing
GET Delegating /messages/resources/main.css FilterProxy <security:http <security:http security="none" security="none" pattern="/resources/**"> pattern=" pattern="/resources/**"> pattern="/resources/** /resources/**""Filter Filter <security:intercept-url <security:intercept-url ChainProxy pattern="/resources/.css" ChainProxy pattern="/resources/.css" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" Exception use-expressions="true"> use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
143
Does /resources/main.css match /resources/**
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"> pattern="/resources/**">
Filter Filter <security:intercept-url <security:intercept-url ChainProxy pattern="/resources/.css" ChainProxy pattern="/resources/.css" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" Exception use-expressions="true"> use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
144
Yes, so select
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"> pattern="/resources/**">
Filter Filter <security:intercept-url <security:intercept-url ChainProxy "" pattern="/resources/.css" ChainProxy pattern=" pattern="/resources/.css" pattern="/resources/.css /resources/.css access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> Exception use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
145
Does /resources/main.css match /resources/.css?
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"> pattern="/resources/**">
Filter Filter <security:intercept-url <security:intercept-url ChainProxy "" pattern="/resources/.css" ChainProxy pattern=" pattern="/resources/.css" pattern="/resources/.css /resources/.css access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> Exception use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
146
Does /resources/main.css match /resources/.css?
Unauthenticated Request to Protected Resource HTTP
Request Processing
Delegating FilterProxy <security:http <security:http security="none" security="none"
GET /messages/
pattern="/resources/**"> pattern="/resources/**">
Filter Filter <security:intercept-url <security:intercept-url ChainProxy pattern="/resources/.css" ChainProxy pattern="/resources/.css" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> <security:http <security:http auto-config="true" auto-config="true" use-expressions="true"> Exception use-expressions="true"> <security:intercept-url pattern="/**" TranslationFilter <security:intercept-url pattern="/**" access="hasRole('ROLE_')"/> access="hasRole('ROLE_')"/> ... ...
147
No, it does not match. No more patterns for this
, so grant access
Log Out
148
src/main/webapp/WEB-INF/security.xml <security:http <security:http use-expressions="true"> use-expressions="true"> ... ... <security: <security: /> />
149
JSP Tags
150
src/main/webapp/WEB-INF/views/header.jspx <jsp:root <jsp:root ……
xmlns:sec="http://www.springframework.org/security/tags" xmlns:sec="http://www.springframework.org/security/tags">>
<sec:authorize <sec:authorize access="authenticated"> access="authenticated"> …… is is the the authenticated authenticated …… <span <span class="navbar-text"> class="navbar-text"> Welcome, Welcome, <sec:authentication <sec:authentication property="name"/> property="name"/> …… 151
Method Level Security
152
src/main/webapp/WEB-INF/security.xml <security:global-method-security <security:global-method-security pre-post-annotations="true"/> pre-post-annotations="true"/>
153
MessageRepository.java @PostAuthorize("hasRole('ROLE_')") @PostAuthorize("hasRole('ROLE_')") Message Message findOne(Long findOne(Long id); id);
154
Method Level Security
MessageRepository
Bean PostProcessor
Should I secure this Object?
ApplicationContext
155
Method Level Security
MessageRepository
Bean PostProcessor
Yes, it has a Security Annotation on it
ApplicationContext
156
Method Level Security
Secure MessageRepository
Bean PostProcessor
Replace it with a Secure implementation
ApplicationContext
157
SecureMessageRepository public class SecureMessageRepository implements MessageRepository { public Message findOne(Long id) { // PreAuthorize checks Message result = delegate.findOne(id); // PostAuthorize checks return result; } … // delegate = original MessageRepository private MessageRepository delegate; } 158
Learn More. Stay Connected. At SpringOne 2GX: • When and why would I use OAuth2? • Making Connections with Spring Social Web: springsource.org • Github: github.com/rwinch/getting-started-springsecurity-31 • Newsletter: springsource.org/news-events • Twitter: twitter.com/SpringSecurity twitter.com/rob_winch • YouTube: youtube.com//SpringSourceDev • LinkedIn: springsource.org/linkedin 159