|
|
|
@ -35,11 +35,13 @@ import org.springframework.security.authorization.AuthorizationDeniedException; |
|
|
|
import org.springframework.security.core.AuthenticationException; |
|
|
|
import org.springframework.security.core.AuthenticationException; |
|
|
|
import org.springframework.security.core.GrantedAuthority; |
|
|
|
import org.springframework.security.core.GrantedAuthority; |
|
|
|
import org.springframework.security.web.AuthenticationEntryPoint; |
|
|
|
import org.springframework.security.web.AuthenticationEntryPoint; |
|
|
|
|
|
|
|
import org.springframework.security.web.WebAttributes; |
|
|
|
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint; |
|
|
|
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint; |
|
|
|
import org.springframework.security.web.savedrequest.NullRequestCache; |
|
|
|
import org.springframework.security.web.savedrequest.NullRequestCache; |
|
|
|
import org.springframework.security.web.savedrequest.RequestCache; |
|
|
|
import org.springframework.security.web.savedrequest.RequestCache; |
|
|
|
import org.springframework.security.web.util.ThrowableAnalyzer; |
|
|
|
import org.springframework.security.web.util.ThrowableAnalyzer; |
|
|
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher; |
|
|
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher; |
|
|
|
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* An {@link AccessDeniedHandler} that adapts {@link AuthenticationEntryPoint}s based on |
|
|
|
* An {@link AccessDeniedHandler} that adapts {@link AuthenticationEntryPoint}s based on |
|
|
|
@ -62,8 +64,8 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher; |
|
|
|
* |
|
|
|
* |
|
|
|
* <code> |
|
|
|
* <code> |
|
|
|
* AccessDeniedHandler handler = DelegatingMissingAuthorityAccessDeniedHandler.builder() |
|
|
|
* AccessDeniedHandler handler = DelegatingMissingAuthorityAccessDeniedHandler.builder() |
|
|
|
* .authorities("FACTOR_OTT").commence(new LoginUrlAuthenticationEntryPoint("/login")) |
|
|
|
* .addEntryPointFor(new LoginUrlAuthenticationEntryPoint("/login"), "FACTOR_OTT") |
|
|
|
* .authorities("FACTOR_PASSWORD")... |
|
|
|
* .addEntryPointFor(new MyCustomEntryPoint(), "FACTOR_PASSWORD") |
|
|
|
* .build(); |
|
|
|
* .build(); |
|
|
|
* </code> |
|
|
|
* </code> |
|
|
|
* |
|
|
|
* |
|
|
|
@ -84,6 +86,7 @@ public final class DelegatingMissingAuthorityAccessDeniedHandler implements Acce |
|
|
|
private AccessDeniedHandler defaultAccessDeniedHandler = new AccessDeniedHandlerImpl(); |
|
|
|
private AccessDeniedHandler defaultAccessDeniedHandler = new AccessDeniedHandlerImpl(); |
|
|
|
|
|
|
|
|
|
|
|
private DelegatingMissingAuthorityAccessDeniedHandler(Map<String, AuthenticationEntryPoint> entryPoints) { |
|
|
|
private DelegatingMissingAuthorityAccessDeniedHandler(Map<String, AuthenticationEntryPoint> entryPoints) { |
|
|
|
|
|
|
|
Assert.notEmpty(entryPoints, "entryPoints cannot be empty"); |
|
|
|
this.entryPoints = entryPoints; |
|
|
|
this.entryPoints = entryPoints; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -97,7 +100,7 @@ public final class DelegatingMissingAuthorityAccessDeniedHandler implements Acce |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
this.requestCache.saveRequest(request, response); |
|
|
|
this.requestCache.saveRequest(request, response); |
|
|
|
request.setAttribute(GrantedAuthority.MISSING_AUTHORITIES_ATTRIBUTE, List.of(needed)); |
|
|
|
request.setAttribute(WebAttributes.MISSING_AUTHORITIES, List.of(needed)); |
|
|
|
String message = String.format("Missing Authorities %s", List.of(needed)); |
|
|
|
String message = String.format("Missing Authorities %s", List.of(needed)); |
|
|
|
AuthenticationException ex = new InsufficientAuthenticationException(message, denied); |
|
|
|
AuthenticationException ex = new InsufficientAuthenticationException(message, denied); |
|
|
|
entryPoint.commence(request, response, ex); |
|
|
|
entryPoint.commence(request, response, ex); |
|
|
|
@ -112,6 +115,7 @@ public final class DelegatingMissingAuthorityAccessDeniedHandler implements Acce |
|
|
|
* @param defaultAccessDeniedHandler the default {@link AccessDeniedHandler} to use |
|
|
|
* @param defaultAccessDeniedHandler the default {@link AccessDeniedHandler} to use |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setDefaultAccessDeniedHandler(AccessDeniedHandler defaultAccessDeniedHandler) { |
|
|
|
public void setDefaultAccessDeniedHandler(AccessDeniedHandler defaultAccessDeniedHandler) { |
|
|
|
|
|
|
|
Assert.notNull(defaultAccessDeniedHandler, "defaultAccessDeniedHandler cannot be null"); |
|
|
|
this.defaultAccessDeniedHandler = defaultAccessDeniedHandler; |
|
|
|
this.defaultAccessDeniedHandler = defaultAccessDeniedHandler; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -123,6 +127,7 @@ public final class DelegatingMissingAuthorityAccessDeniedHandler implements Acce |
|
|
|
* @param requestCache the {@link RequestCache} to use |
|
|
|
* @param requestCache the {@link RequestCache} to use |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setRequestCache(RequestCache requestCache) { |
|
|
|
public void setRequestCache(RequestCache requestCache) { |
|
|
|
|
|
|
|
Assert.notNull(requestCache, "requestCachgrantedaue cannot be null"); |
|
|
|
this.requestCache = requestCache; |
|
|
|
this.requestCache = requestCache; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -158,57 +163,44 @@ public final class DelegatingMissingAuthorityAccessDeniedHandler implements Acce |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static final class Builder { |
|
|
|
public static final class Builder { |
|
|
|
|
|
|
|
|
|
|
|
private final Map<String, DelegatingAuthenticationEntryPoint.Builder> entryPointByRequestMatcherByAuthority = new LinkedHashMap<>(); |
|
|
|
private final Map<String, DelegatingAuthenticationEntryPoint.Builder> entryPointBuilderByAuthority = new LinkedHashMap<>(); |
|
|
|
|
|
|
|
|
|
|
|
private Builder() { |
|
|
|
private Builder() { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DelegatingAuthenticationEntryPoint.Builder entryPointBuilder(String authority) { |
|
|
|
|
|
|
|
return this.entryPointByRequestMatcherByAuthority.computeIfAbsent(authority, |
|
|
|
|
|
|
|
(k) -> DelegatingAuthenticationEntryPoint.builder()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void entryPoint(String authority, AuthenticationEntryPoint entryPoint) { |
|
|
|
|
|
|
|
DelegatingAuthenticationEntryPoint.Builder builder = DelegatingAuthenticationEntryPoint.builder() |
|
|
|
|
|
|
|
.addEntryPointFor(entryPoint, AnyRequestMatcher.INSTANCE); |
|
|
|
|
|
|
|
this.entryPointByRequestMatcherByAuthority.put(authority, builder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Bind these authorities to the given {@link AuthenticationEntryPoint} |
|
|
|
* Use this {@link AuthenticationEntryPoint} when the given |
|
|
|
* @param entryPoint the {@link AuthenticationEntryPoint} for the given |
|
|
|
* {@code missingAuthority} is missing from the authenticated user |
|
|
|
* authorities |
|
|
|
* @param entryPoint the {@link AuthenticationEntryPoint} for the given authority |
|
|
|
* @param authorities the authorities |
|
|
|
* @param missingAuthority the authority |
|
|
|
* @return the {@link Builder} for further configurations |
|
|
|
* @return the {@link Builder} for further configurations |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Builder addEntryPointFor(AuthenticationEntryPoint entryPoint, String... authorities) { |
|
|
|
public Builder addEntryPointFor(AuthenticationEntryPoint entryPoint, String missingAuthority) { |
|
|
|
for (String authority : authorities) { |
|
|
|
DelegatingAuthenticationEntryPoint.Builder builder = DelegatingAuthenticationEntryPoint.builder() |
|
|
|
Builder.this.entryPoint(authority, entryPoint); |
|
|
|
.addEntryPointFor(entryPoint, AnyRequestMatcher.INSTANCE); |
|
|
|
} |
|
|
|
this.entryPointBuilderByAuthority.put(missingAuthority, builder); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Bind these authorities to the given {@link AuthenticationEntryPoint} |
|
|
|
* Use this {@link AuthenticationEntryPoint} when the given |
|
|
|
|
|
|
|
* {@code missingAuthority} is missing from the authenticated user |
|
|
|
* @param entryPoint a consumer to configure the underlying |
|
|
|
* @param entryPoint a consumer to configure the underlying |
|
|
|
* {@link DelegatingAuthenticationEntryPoint} |
|
|
|
* {@link DelegatingAuthenticationEntryPoint} |
|
|
|
* @param authorities the authorities |
|
|
|
* @param missingAuthority the authority |
|
|
|
* @return the {@link Builder} for further configurations |
|
|
|
* @return the {@link Builder} for further configurations |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Builder addEntryPointFor(Consumer<DelegatingAuthenticationEntryPoint.Builder> entryPoint, |
|
|
|
public Builder addEntryPointFor(Consumer<DelegatingAuthenticationEntryPoint.Builder> entryPoint, |
|
|
|
String... authorities) { |
|
|
|
String missingAuthority) { |
|
|
|
for (String authority : authorities) { |
|
|
|
entryPoint.accept(this.entryPointBuilderByAuthority.computeIfAbsent(missingAuthority, |
|
|
|
entryPoint.accept(Builder.this.entryPointBuilder(authority)); |
|
|
|
(k) -> DelegatingAuthenticationEntryPoint.builder())); |
|
|
|
} |
|
|
|
|
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public DelegatingMissingAuthorityAccessDeniedHandler build() { |
|
|
|
public DelegatingMissingAuthorityAccessDeniedHandler build() { |
|
|
|
Map<String, AuthenticationEntryPoint> entryPointByAuthority = new LinkedHashMap<>(); |
|
|
|
Map<String, AuthenticationEntryPoint> entryPointByAuthority = new LinkedHashMap<>(); |
|
|
|
for (String authority : this.entryPointByRequestMatcherByAuthority.keySet()) { |
|
|
|
this.entryPointBuilderByAuthority.forEach((key, value) -> entryPointByAuthority.put(key, value.build())); |
|
|
|
entryPointByAuthority.put(authority, this.entryPointByRequestMatcherByAuthority.get(authority).build()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return new DelegatingMissingAuthorityAccessDeniedHandler(entryPointByAuthority); |
|
|
|
return new DelegatingMissingAuthorityAccessDeniedHandler(entryPointByAuthority); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|