|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright 2002-2013 the original author or authors.
|
|
|
+ * Copyright 2002-2018 the original author or authors.
|
|
|
*
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
* you may not use this file except in compliance with the License.
|
|
@@ -23,6 +23,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
|
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
|
|
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
|
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
|
|
+import org.springframework.security.web.access.RequestMatcherDelegatingAccessDeniedHandler;
|
|
|
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
|
|
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
|
|
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
|
@@ -70,6 +71,8 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|
|
|
|
|
private LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> defaultEntryPointMappings = new LinkedHashMap<>();
|
|
|
|
|
|
+ private LinkedHashMap<RequestMatcher, AccessDeniedHandler> defaultDeniedHandlerMappings = new LinkedHashMap<>();
|
|
|
+
|
|
|
/**
|
|
|
* Creates a new instance
|
|
|
* @see HttpSecurity#exceptionHandling()
|
|
@@ -104,6 +107,26 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets a default {@link AccessDeniedHandler} to be used which prefers being
|
|
|
+ * invoked for the provided {@link RequestMatcher}. If only a single default
|
|
|
+ * {@link AccessDeniedHandler} is specified, it will be what is used for the
|
|
|
+ * default {@link AccessDeniedHandler}. If multiple default
|
|
|
+ * {@link AccessDeniedHandler} instances are configured, then a
|
|
|
+ * {@link RequestMatcherDelegatingAccessDeniedHandler} will be used.
|
|
|
+ *
|
|
|
+ * @param deniedHandler the {@link AccessDeniedHandler} to use
|
|
|
+ * @param preferredMatcher the {@link RequestMatcher} for this default
|
|
|
+ * {@link AccessDeniedHandler}
|
|
|
+ * @return the {@link ExceptionHandlingConfigurer} for further customizations
|
|
|
+ * @since 5.1
|
|
|
+ */
|
|
|
+ public ExceptionHandlingConfigurer<H> defaultAccessDeniedHandlerFor(
|
|
|
+ AccessDeniedHandler deniedHandler, RequestMatcher preferredMatcher) {
|
|
|
+ this.defaultDeniedHandlerMappings.put(preferredMatcher, deniedHandler);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Sets the {@link AuthenticationEntryPoint} to be used.
|
|
|
*
|
|
@@ -169,13 +192,27 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|
|
AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http);
|
|
|
ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(
|
|
|
entryPoint, getRequestCache(http));
|
|
|
- if (accessDeniedHandler != null) {
|
|
|
- exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandler);
|
|
|
- }
|
|
|
+ AccessDeniedHandler deniedHandler = getAccessDeniedHandler(http);
|
|
|
+ exceptionTranslationFilter.setAccessDeniedHandler(deniedHandler);
|
|
|
exceptionTranslationFilter = postProcess(exceptionTranslationFilter);
|
|
|
http.addFilter(exceptionTranslationFilter);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the {@link AccessDeniedHandler} according to the rules specified by
|
|
|
+ * {@link #accessDeniedHandler(AccessDeniedHandler)}
|
|
|
+ * @param http the {@link HttpSecurity} used to look up shared
|
|
|
+ * {@link AccessDeniedHandler}
|
|
|
+ * @return the {@link AccessDeniedHandler} to use
|
|
|
+ */
|
|
|
+ AccessDeniedHandler getAccessDeniedHandler(H http) {
|
|
|
+ AccessDeniedHandler deniedHandler = this.accessDeniedHandler;
|
|
|
+ if (deniedHandler == null) {
|
|
|
+ deniedHandler = createDefaultDeniedHandler(http);
|
|
|
+ }
|
|
|
+ return deniedHandler;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Gets the {@link AuthenticationEntryPoint} according to the rules specified by
|
|
|
* {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
|
|
@@ -191,16 +228,28 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|
|
return entryPoint;
|
|
|
}
|
|
|
|
|
|
+ private AccessDeniedHandler createDefaultDeniedHandler(H http) {
|
|
|
+ if (this.defaultDeniedHandlerMappings.isEmpty()) {
|
|
|
+ return new AccessDeniedHandlerImpl();
|
|
|
+ }
|
|
|
+ if (this.defaultDeniedHandlerMappings.size() == 1) {
|
|
|
+ return this.defaultDeniedHandlerMappings.values().iterator().next();
|
|
|
+ }
|
|
|
+ return new RequestMatcherDelegatingAccessDeniedHandler(
|
|
|
+ this.defaultDeniedHandlerMappings,
|
|
|
+ new AccessDeniedHandlerImpl());
|
|
|
+ }
|
|
|
+
|
|
|
private AuthenticationEntryPoint createDefaultEntryPoint(H http) {
|
|
|
- if (defaultEntryPointMappings.isEmpty()) {
|
|
|
+ if (this.defaultEntryPointMappings.isEmpty()) {
|
|
|
return new Http403ForbiddenEntryPoint();
|
|
|
}
|
|
|
- if (defaultEntryPointMappings.size() == 1) {
|
|
|
- return defaultEntryPointMappings.values().iterator().next();
|
|
|
+ if (this.defaultEntryPointMappings.size() == 1) {
|
|
|
+ return this.defaultEntryPointMappings.values().iterator().next();
|
|
|
}
|
|
|
DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(
|
|
|
- defaultEntryPointMappings);
|
|
|
- entryPoint.setDefaultEntryPoint(defaultEntryPointMappings.values().iterator()
|
|
|
+ this.defaultEntryPointMappings);
|
|
|
+ entryPoint.setDefaultEntryPoint(this.defaultEntryPointMappings.values().iterator()
|
|
|
.next());
|
|
|
return entryPoint;
|
|
|
}
|