1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.security.ui;
17
18 import org.springframework.security.AccessDeniedException;
19 import org.springframework.security.SpringSecurityException;
20 import org.springframework.security.AuthenticationException;
21 import org.springframework.security.AuthenticationTrustResolver;
22 import org.springframework.security.AuthenticationTrustResolverImpl;
23 import org.springframework.security.InsufficientAuthenticationException;
24 import org.springframework.security.context.SecurityContextHolder;
25 import org.springframework.security.ui.savedrequest.SavedRequest;
26 import org.springframework.security.util.PortResolver;
27 import org.springframework.security.util.PortResolverImpl;
28 import org.springframework.security.util.ThrowableAnalyzer;
29 import org.springframework.security.util.ThrowableCauseExtractor;
30 import org.springframework.beans.factory.InitializingBean;
31
32 import org.springframework.util.Assert;
33
34 import java.io.IOException;
35
36 import javax.servlet.FilterChain;
37 import javax.servlet.ServletException;
38 import javax.servlet.ServletRequest;
39 import javax.servlet.ServletResponse;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletResponse;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public class ExceptionTranslationFilter extends SpringSecurityFilter implements InitializingBean {
78
79
80
81 private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
82 private AuthenticationEntryPoint authenticationEntryPoint;
83 private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
84 private PortResolver portResolver = new PortResolverImpl();
85 private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
86 private boolean createSessionAllowed = true;
87
88
89
90 public void afterPropertiesSet() throws Exception {
91 Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified");
92 Assert.notNull(portResolver, "portResolver must be specified");
93 Assert.notNull(authenticationTrustResolver, "authenticationTrustResolver must be specified");
94 Assert.notNull(throwableAnalyzer, "throwableAnalyzer must be specified");
95 }
96
97 public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException,
98 ServletException {
99
100 try {
101 chain.doFilter(request, response);
102
103 if (logger.isDebugEnabled()) {
104 logger.debug("Chain processed normally");
105 }
106 }
107 catch (IOException ex) {
108 throw ex;
109 }
110 catch (Exception ex) {
111
112 Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
113 SpringSecurityException ase = (SpringSecurityException)
114 this.throwableAnalyzer.getFirstThrowableOfType(SpringSecurityException.class, causeChain);
115
116 if (ase != null) {
117 handleException(request, response, chain, ase);
118 }
119 else {
120
121 if (ex instanceof ServletException) {
122 throw (ServletException) ex;
123 }
124 else if (ex instanceof RuntimeException) {
125 throw (RuntimeException) ex;
126 }
127
128
129 throw new RuntimeException(ex);
130 }
131 }
132 }
133
134 public AuthenticationEntryPoint getAuthenticationEntryPoint() {
135 return authenticationEntryPoint;
136 }
137
138 public AuthenticationTrustResolver getAuthenticationTrustResolver() {
139 return authenticationTrustResolver;
140 }
141
142 public PortResolver getPortResolver() {
143 return portResolver;
144 }
145
146 private void handleException(ServletRequest request, ServletResponse response, FilterChain chain,
147 SpringSecurityException exception) throws IOException, ServletException {
148 if (exception instanceof AuthenticationException) {
149 if (logger.isDebugEnabled()) {
150 logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);
151 }
152
153 sendStartAuthentication(request, response, chain, (AuthenticationException) exception);
154 }
155 else if (exception instanceof AccessDeniedException) {
156 if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
157 if (logger.isDebugEnabled()) {
158 logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
159 exception);
160 }
161
162 sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException(
163 "Full authentication is required to access this resource"));
164 }
165 else {
166 if (logger.isDebugEnabled()) {
167 logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
168 exception);
169 }
170
171 accessDeniedHandler.handle(request, response, (AccessDeniedException) exception);
172 }
173 }
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 public boolean isCreateSessionAllowed() {
190 return createSessionAllowed;
191 }
192
193 protected void sendStartAuthentication(ServletRequest request, ServletResponse response, FilterChain chain,
194 AuthenticationException reason) throws ServletException, IOException {
195 HttpServletRequest httpRequest = (HttpServletRequest) request;
196
197 SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver);
198
199 if (logger.isDebugEnabled()) {
200 logger.debug("Authentication entry point being called; SavedRequest added to Session: " + savedRequest);
201 }
202
203 if (createSessionAllowed) {
204
205
206 httpRequest.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
207 }
208
209
210
211 SecurityContextHolder.getContext().setAuthentication(null);
212
213 authenticationEntryPoint.commence(httpRequest, response, reason);
214 }
215
216 public void setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) {
217 Assert.notNull(accessDeniedHandler, "AccessDeniedHandler required");
218 this.accessDeniedHandler = accessDeniedHandler;
219 }
220
221 public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
222 this.authenticationEntryPoint = authenticationEntryPoint;
223 }
224
225 public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
226 this.authenticationTrustResolver = authenticationTrustResolver;
227 }
228
229 public void setCreateSessionAllowed(boolean createSessionAllowed) {
230 this.createSessionAllowed = createSessionAllowed;
231 }
232
233 public void setPortResolver(PortResolver portResolver) {
234 this.portResolver = portResolver;
235 }
236
237 public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) {
238 this.throwableAnalyzer = throwableAnalyzer;
239 }
240
241 public int getOrder() {
242 return FilterChainOrder.EXCEPTION_TRANSLATION_FILTER;
243 }
244
245
246
247
248
249 private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer {
250
251
252
253 protected void initExtractorMap() {
254 super.initExtractorMap();
255
256 registerExtractor(ServletException.class, new ThrowableCauseExtractor() {
257 public Throwable extractCause(Throwable throwable) {
258 ThrowableAnalyzer.verifyThrowableHierarchy(throwable, ServletException.class);
259 return ((ServletException) throwable).getRootCause();
260 }
261 });
262 }
263
264 }
265
266 }