mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-14 06:13:30 +00:00
Polish Javadoc
Fixes: gh-5186
This commit is contained in:
parent
c67ce144b9
commit
151b545ed0
@ -55,7 +55,7 @@ import java.lang.annotation.Target;
|
||||
* @EnableWebFluxSecurity
|
||||
* public class MyExplicitSecurityConfiguration {
|
||||
* @Bean
|
||||
* SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
* public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
* http
|
||||
* .authorizeExchange()
|
||||
* .anyExchange().authenticated()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,9 @@ import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A {@link MethodInterceptor} that supports {@link PreAuthorize} and {@link PostAuthorize} for methods that return
|
||||
* {@link Mono} or {@link Flux}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -49,6 +52,12 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
|
||||
|
||||
private final PostInvocationAuthorizationAdvice postAdvice;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param attributeSource the {@link MethodSecurityMetadataSource} to use
|
||||
* @param preInvocationAdvice the {@link PreInvocationAuthorizationAdvice} to use
|
||||
* @param postInvocationAdvice the {@link PostInvocationAuthorizationAdvice} to use
|
||||
*/
|
||||
public PrePostAdviceReactiveMethodInterceptor(MethodSecurityMetadataSource attributeSource, PreInvocationAuthorizationAdvice preInvocationAdvice, PostInvocationAuthorizationAdvice postInvocationAdvice) {
|
||||
Assert.notNull(attributeSource, "attributeSource cannot be null");
|
||||
Assert.notNull(preInvocationAdvice, "preInvocationAdvice cannot be null");
|
||||
|
@ -25,6 +25,7 @@ import reactor.core.publisher.Mono;
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ReactiveAuthenticationManager {
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,9 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
/**
|
||||
* A {@link ReactiveAuthenticationManager} that uses a {@link ReactiveUserDetailsService} to validate the provided
|
||||
* username and password.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -49,6 +52,11 @@ public class UserDetailsRepositoryReactiveAuthenticationManager implements React
|
||||
.map( u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities()) );
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link PasswordEncoder} that is used for validating the password. The default is
|
||||
* {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()}
|
||||
* @param passwordEncoder the {@link PasswordEncoder} to use. Cannot be null
|
||||
*/
|
||||
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
||||
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
|
@ -26,6 +26,7 @@ import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* A {@link Map} based implementation of {@link ReactiveUserDetailsService}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
@ -33,14 +34,26 @@ import reactor.core.publisher.Mono;
|
||||
public class MapReactiveUserDetailsService implements ReactiveUserDetailsService {
|
||||
private final Map<String, UserDetails> users;
|
||||
|
||||
/**
|
||||
* Creates a new instance using a {@link Map} that must be non blocking.
|
||||
* @param users a {@link Map} of users to use.
|
||||
*/
|
||||
public MapReactiveUserDetailsService(Map<String, UserDetails> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param users the {@link UserDetails} to use
|
||||
*/
|
||||
public MapReactiveUserDetailsService(UserDetails... users) {
|
||||
this(Arrays.asList(users));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param users the {@link UserDetails} to use
|
||||
*/
|
||||
public MapReactiveUserDetailsService(Collection<UserDetails> users) {
|
||||
Assert.notEmpty(users, "users cannot be null or empty");
|
||||
this.users = users.stream().collect(Collectors.toConcurrentMap( u -> getKey(u.getUsername()), Function.identity()));
|
||||
|
@ -16,11 +16,20 @@
|
||||
|
||||
package org.springframework.security.core.userdetails;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* An API for finding the {@link UserDetails} by username.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ReactiveUserDetailsService {
|
||||
|
||||
/**
|
||||
* Find the {@link UserDetails} by username.
|
||||
* @param username the username to look up
|
||||
* @return the {@link UserDetails}. Cannot be null
|
||||
*/
|
||||
Mono<UserDetails> findByUsername(String username);
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import reactor.core.publisher.Mono;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* The default {@link ServerRedirectStrategy} to use.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -55,6 +57,10 @@ public class DefaultServerRedirectStrategy implements ServerRedirectStrategy {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link HttpStatus} to use for the redirect.
|
||||
* @param httpStatus the status to use. Cannot be null
|
||||
*/
|
||||
public void setHttpStatus(HttpStatus httpStatus) {
|
||||
Assert.notNull(httpStatus, "httpStatus cannot be null");
|
||||
this.httpStatus = httpStatus;
|
||||
|
@ -29,6 +29,9 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link ServerAuthenticationEntryPoint} which delegates to multiple {@link ServerAuthenticationEntryPoint} based
|
||||
* on a {@link ServerWebExchangeMatcher}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -26,6 +26,9 @@ import reactor.core.publisher.Mono;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SecurityWebFilterChain} that leverages a {@link ServerWebExchangeMatcher} to determine which
|
||||
* {@link WebFilter} to execute.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -21,13 +21,25 @@ import org.springframework.web.server.WebFilter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Defines a filter chain which is capable of being matched against a {@link ServerWebExchange} in order to decide
|
||||
* whether it applies to that request.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface SecurityWebFilterChain {
|
||||
|
||||
/**
|
||||
* Determines if this {@link SecurityWebFilterChain} matches the provided {@link ServerWebExchange}
|
||||
* @param exchange the {@link ServerWebExchange}
|
||||
* @return true if it matches, else false
|
||||
*/
|
||||
Mono<Boolean> matches(ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* The {@link WebFilter} to use
|
||||
* @return
|
||||
*/
|
||||
Flux<WebFilter> getWebFilters();
|
||||
}
|
||||
|
@ -21,11 +21,20 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Used to request authentication
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ServerAuthenticationEntryPoint {
|
||||
|
||||
/**
|
||||
* Initiates the authentication flow
|
||||
*
|
||||
* @param exchange
|
||||
* @param e
|
||||
* @return {@code Mono<Void>} to indicate when the request for authentication is complete
|
||||
*/
|
||||
Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Converts from a {@link ServerWebExchange} to an {@link Authentication} that can be authenticated.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
|
@ -23,10 +23,19 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* A strategy for performing redirects.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ServerRedirectStrategy {
|
||||
|
||||
/**
|
||||
* Performs a redirect based upon the provided {@link ServerWebExchange} and {@link URI}
|
||||
* @param exchange the {@link ServerWebExchange} to use
|
||||
* @param location the location to redirect to
|
||||
* @return {@code Mono<Void>} to indicate when redirect is complete
|
||||
*/
|
||||
Mono<Void> sendRedirect(ServerWebExchange exchange, URI location);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Used to delegate to a List of {@link SecurityWebFilterChain} instances.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -21,6 +21,8 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
|
||||
/**
|
||||
* A composite of the {@link ServerWebExchange} and the {@link WebFilterChain}. This is typically used as a value object
|
||||
* for handling success and failures.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -36,6 +36,27 @@ import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
|
||||
/**
|
||||
* A {@link WebFilter} that performs authentication of a particular request. An outline of the logic:
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* A request comes in and if it does not match {@link #setRequiresAuthenticationMatcher(ServerWebExchangeMatcher)},
|
||||
* then this filter does nothing and the {@link WebFilterChain} is continued. If it does match then...
|
||||
* </li>
|
||||
* <li>
|
||||
* An attempt to convert the {@link ServerWebExchange} into an {@link Authentication} is made. If the result is
|
||||
* empty, then the filter does nothing more and the {@link WebFilterChain} is continued. If it does create an
|
||||
* {@link Authentication}...
|
||||
* </li>
|
||||
* <li>
|
||||
* The {@link ReactiveAuthenticationManager} specified in
|
||||
* {@link #AuthenticationWebFilter(ReactiveAuthenticationManager)} is used to perform authentication.
|
||||
* </li>
|
||||
* <li>
|
||||
* If authentication is successful, {@link ServerAuthenticationSuccessHandler} is invoked and the authentication
|
||||
* is set on {@link ReactiveSecurityContextHolder}, else {@link ServerAuthenticationFailureHandler} is invoked
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
@ -54,6 +75,10 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
|
||||
private ServerWebExchangeMatcher requiresAuthenticationMatcher = ServerWebExchangeMatchers.anyExchange();
|
||||
|
||||
/**
|
||||
* Creates an instance
|
||||
* @param authenticationManager the authentication manager to use
|
||||
*/
|
||||
public AuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager) {
|
||||
Assert.notNull(authenticationManager, "authenticationManager cannot be null");
|
||||
this.authenticationManager = authenticationManager;
|
||||
@ -87,26 +112,53 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
.subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repository for persisting the SecurityContext. Default is {@link NoOpServerSecurityContextRepository}
|
||||
* @param securityContextRepository the repository to use
|
||||
*/
|
||||
public void setSecurityContextRepository(
|
||||
ServerSecurityContextRepository securityContextRepository) {
|
||||
Assert.notNull(securityContextRepository, "securityContextRepository cannot be null");
|
||||
this.securityContextRepository = securityContextRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authentication success handler. Default is {@link WebFilterChainServerAuthenticationSuccessHandler}
|
||||
* @param authenticationSuccessHandler the success handler to use
|
||||
*/
|
||||
public void setAuthenticationSuccessHandler(ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
|
||||
Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
|
||||
this.authenticationSuccessHandler = authenticationSuccessHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy used for converting from a {@link ServerWebExchange} to an {@link Authentication} used for
|
||||
* authenticating with the provided {@link ReactiveAuthenticationManager}. If the result is empty, then it signals
|
||||
* that no authentication attempt should be made. The default converter is
|
||||
* {@link ServerHttpBasicAuthenticationConverter}
|
||||
* @param authenticationConverter the converter to use
|
||||
*/
|
||||
public void setAuthenticationConverter(Function<ServerWebExchange, Mono<Authentication>> authenticationConverter) {
|
||||
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
|
||||
this.authenticationConverter = authenticationConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the failure handler used when authentication fails. The default is to prompt for basic authentication.
|
||||
* @param authenticationFailureHandler the handler to use. Cannot be null.
|
||||
*/
|
||||
public void setAuthenticationFailureHandler(
|
||||
ServerAuthenticationFailureHandler authenticationFailureHandler) {
|
||||
Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null");
|
||||
this.authenticationFailureHandler = authenticationFailureHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the matcher used to determine when creating an {@link Authentication} from
|
||||
* {@link #setAuthenticationConverter(Function)} to be authentication. If the converter returns an empty
|
||||
* result, then no authentication is attempted. The default is any request
|
||||
* @param requiresAuthenticationMatcher the matcher to use. Cannot be null.
|
||||
*/
|
||||
public void setRequiresAuthenticationMatcher(
|
||||
ServerWebExchangeMatcher requiresAuthenticationMatcher) {
|
||||
Assert.notNull(requiresAuthenticationMatcher, "requiresAuthenticationMatcher cannot be null");
|
||||
|
@ -25,6 +25,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Prompts a user for HTTP Basic authentication.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
|
@ -43,11 +43,19 @@ public class RedirectServerAuthenticationEntryPoint
|
||||
|
||||
private ServerRequestCache requestCache = new WebSessionServerRequestCache();
|
||||
|
||||
/**
|
||||
* Creates an instance
|
||||
* @param location the location to redirect to (i.e. "/logout-success")
|
||||
*/
|
||||
public RedirectServerAuthenticationEntryPoint(String location) {
|
||||
Assert.notNull(location, "location cannot be null");
|
||||
this.location = URI.create(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* The request cache to use to save the request before sending a redirect.
|
||||
* @param requestCache the cache to redirect to.
|
||||
*/
|
||||
public void setRequestCache(ServerRequestCache requestCache) {
|
||||
Assert.notNull(requestCache, "requestCache cannot be null");
|
||||
this.requestCache = requestCache;
|
||||
|
@ -37,6 +37,10 @@ public class RedirectServerAuthenticationFailureHandler
|
||||
|
||||
private ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy();
|
||||
|
||||
/**
|
||||
* Creates an instance
|
||||
* @param location the location to redirect to (i.e. "/login?failed")
|
||||
*/
|
||||
public RedirectServerAuthenticationFailureHandler(String location) {
|
||||
Assert.notNull(location, "location cannot be null");
|
||||
this.location = URI.create(location);
|
||||
|
@ -29,6 +29,8 @@ import reactor.core.publisher.Mono;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Performs a redirect on authentication success. The default is to redirect to a saved request if present and
|
||||
* otherwise "/".
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -40,12 +42,24 @@ public class RedirectServerAuthenticationSuccessHandler
|
||||
|
||||
private ServerRequestCache requestCache = new WebSessionServerRequestCache();
|
||||
|
||||
/**
|
||||
* Creates a new instance with location of "/"
|
||||
*/
|
||||
public RedirectServerAuthenticationSuccessHandler() {}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified location
|
||||
* @param location the location to redirect if the no request is cached in
|
||||
* {@link #setRequestCache(ServerRequestCache)}
|
||||
*/
|
||||
public RedirectServerAuthenticationSuccessHandler(String location) {
|
||||
this.location = URI.create(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ServerRequestCache} used to redirect to. Default is {@link WebSessionServerRequestCache}.
|
||||
* @param requestCache the cache to use
|
||||
*/
|
||||
public void setRequestCache(ServerRequestCache requestCache) {
|
||||
Assert.notNull(requestCache, "requestCache cannot be null");
|
||||
this.requestCache = requestCache;
|
||||
|
@ -23,6 +23,7 @@ import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Adapts a {@link ServerAuthenticationEntryPoint} into a {@link ServerAuthenticationFailureHandler}
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -22,9 +22,17 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.web.server.WebFilterExchange;
|
||||
|
||||
/**
|
||||
* Handles authentication failure
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ServerAuthenticationFailureHandler {
|
||||
/**
|
||||
* Invoked when authentication attempt fails
|
||||
* @param webFilterExchange the exchange
|
||||
* @param exception the reason authentication failed
|
||||
* @return a completion notification (success or error)
|
||||
*/
|
||||
Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception);
|
||||
}
|
||||
|
@ -21,10 +21,17 @@ import org.springframework.security.web.server.WebFilterExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Handles authentication success
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ServerAuthenticationSuccessHandler {
|
||||
/**
|
||||
* Invoked when the application authenticates successfully
|
||||
* @param webFilterExchange the exchange
|
||||
* @param authentication the {@link Authentication}
|
||||
* @return a completion notification (success or error)
|
||||
*/
|
||||
Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange,
|
||||
Authentication authentication);
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Success handler that continues the filter chain after authentication success.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Performs a redirect on log out success.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -21,9 +21,17 @@ import org.springframework.security.web.server.WebFilterExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Handles log out
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see ServerLogoutSuccessHandler
|
||||
*/
|
||||
public interface ServerLogoutHandler {
|
||||
/**
|
||||
* Invoked when log out is requested
|
||||
* @param exchange the exchange
|
||||
* @param authentication the {@link Authentication}
|
||||
* @return a completion notification (success or error)
|
||||
*/
|
||||
Mono<Void> logout(WebFilterExchange exchange, Authentication authentication);
|
||||
}
|
||||
|
@ -21,10 +21,18 @@ import org.springframework.security.web.server.WebFilterExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Strategy for when log out was successfully performed (typically after {@link ServerLogoutHandler} is invoked).
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see ServerLogoutHandler
|
||||
*/
|
||||
public interface ServerLogoutSuccessHandler {
|
||||
|
||||
/**
|
||||
* Invoked after log out was successful
|
||||
* @param exchange the exchange
|
||||
* @param authentication the {@link Authentication}
|
||||
* @return a completion notification (success or error)
|
||||
*/
|
||||
Mono<Void> onLogoutSuccess(WebFilterExchange exchange, Authentication authentication);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* A do nothing implementation of {@link ServerSecurityContextRepository}. Used in stateless applications.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -25,6 +25,9 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.util.context.Context;
|
||||
|
||||
/**
|
||||
* Uses a {@link ServerSecurityContextRepository} to provide the {@link SecurityContext} to initialize the
|
||||
* {@link ReactiveSecurityContextHolder}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -24,8 +24,10 @@ import org.springframework.web.server.ServerWebExchangeDecorator;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Overrides the {@link ServerWebExchange#getPrincipal()} with the provided SecurityContext
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see SecurityContextServerWebExchangeWebFilter
|
||||
*/
|
||||
public class SecurityContextServerWebExchange extends ServerWebExchangeDecorator {
|
||||
private final Mono<SecurityContext> context;
|
||||
|
@ -21,13 +21,9 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.context.Context;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* Populate the {@link Principal} from {@link ServerWebExchange#getPrincipal()} into the
|
||||
* Reactor {@link Context}.
|
||||
* Override the {@link ServerWebExchange#getPrincipal()} to be looked up using {@link ReactiveSecurityContextHolder}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
|
@ -20,9 +20,26 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Strategy used for persisting a {@link SecurityContext} between requests.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see ReactorContextWebFilter
|
||||
*/
|
||||
public interface ServerSecurityContextRepository {
|
||||
|
||||
/**
|
||||
* Saves the SecurityContext
|
||||
* @param exchange the exchange to associate to the SecurityContext
|
||||
* @param context the SecurityContext to save
|
||||
* @return a completion notification (success or error)
|
||||
*/
|
||||
Mono<Void> save(ServerWebExchange exchange, SecurityContext context);
|
||||
|
||||
/**
|
||||
* Loads the SecurityContext associated with the {@link ServerWebExchange}
|
||||
* @param exchange the exchange to look up the {@link SecurityContext}
|
||||
* @return the {@link SecurityContext} to lookup or empty if not found. Never null
|
||||
*/
|
||||
Mono<SecurityContext> load(ServerWebExchange exchange);
|
||||
}
|
||||
|
@ -21,6 +21,13 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Writes cache control related headers.
|
||||
*
|
||||
* <pre>
|
||||
* Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
* Pragma: no-cache
|
||||
* Expires: 0
|
||||
* </pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
|
@ -25,6 +25,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Combines multiple {@link ServerHttpHeadersWriter} instances into a single instance.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
|
@ -24,6 +24,8 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Allows specifying {@link HttpHeaders} that should be written to the response.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -22,6 +22,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Writes the Strict-Transport-Security if the request is secure.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -52,11 +53,19 @@ public final class StrictTransportSecurityServerHttpHeadersWriter
|
||||
return isSecure(exchange) ? delegate.writeHttpHeaders(exchange) : Mono.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if subdomains should be included. Default is true
|
||||
* @param includeSubDomains if subdomains should be included
|
||||
*/
|
||||
public void setIncludeSubDomains(boolean includeSubDomains) {
|
||||
subdomain = includeSubDomains ? " ; includeSubDomains" : "";
|
||||
updateDelegate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max age of the header. Default is a year.
|
||||
* @param maxAge the max age of the header
|
||||
*/
|
||||
public void setMaxAge(Duration maxAge) {
|
||||
this.maxAge = "max-age=" + maxAge.getSeconds();
|
||||
updateDelegate();
|
||||
|
@ -20,6 +20,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* {@code ServerHttpHeadersWriter} implementation for the X-Frame-Options headers.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -20,6 +20,8 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Add the x-xss-protection header.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -33,7 +35,7 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
|
||||
private ServerHttpHeadersWriter delegate;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates a new instance
|
||||
*/
|
||||
public XXssProtectionServerHttpHeadersWriter() {
|
||||
this.enabled = true;
|
||||
|
@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ServerRequestCache} that does nothing. This is used in stateless applications
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -34,6 +34,8 @@ import reactor.core.publisher.Mono;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Generates a default log in page used for authenticating users.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -54,7 +56,6 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
|
||||
result.setStatusCode(HttpStatus.OK);
|
||||
result.getHeaders().setContentType(MediaType.TEXT_HTML);
|
||||
return result.writeWith(createBuffer(exchange));
|
||||
// .doOnError( error -> DataBufferUtils.release(buffer));
|
||||
}
|
||||
|
||||
private Mono<DataBuffer> createBuffer(ServerWebExchange exchange) {
|
||||
|
@ -33,6 +33,8 @@ import reactor.core.publisher.Mono;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Generates a default log out page.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -26,8 +26,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Matches if all the provided {@link ServerWebExchangeMatcher} match
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see OrServerWebExchangeMatcher
|
||||
*/
|
||||
public class AndServerWebExchangeMatcher implements ServerWebExchangeMatcher {
|
||||
private final List<ServerWebExchangeMatcher> matchers;
|
||||
|
@ -34,6 +34,8 @@ import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Matches based upon the accept headers.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ -44,12 +46,20 @@ public class MediaTypeServerWebExchangeMatcher implements ServerWebExchangeMatch
|
||||
private boolean useEquals;
|
||||
private Set<MediaType> ignoredMediaTypes = Collections.emptySet();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param matchingMediaTypes the types to match on
|
||||
*/
|
||||
public MediaTypeServerWebExchangeMatcher(MediaType... matchingMediaTypes) {
|
||||
Assert.notEmpty(matchingMediaTypes, "matchingMediaTypes cannot be null");
|
||||
Assert.noNullElements(matchingMediaTypes, "matchingMediaTypes cannot contain null");
|
||||
this.matchingMediaTypes = Arrays.asList(matchingMediaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param matchingMediaTypes the types to match on
|
||||
*/
|
||||
public MediaTypeServerWebExchangeMatcher(Collection<MediaType> matchingMediaTypes) {
|
||||
Assert.notEmpty(matchingMediaTypes, "matchingMediaTypes cannot be null");
|
||||
Assert.isTrue(!matchingMediaTypes.contains(null), () -> "matchingMediaTypes cannot contain null. Got " + matchingMediaTypes);
|
||||
|
@ -24,8 +24,10 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Matches if any of the provided {@link ServerWebExchangeMatcher} match
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see AndServerWebExchangeMatcher
|
||||
*/
|
||||
public class OrServerWebExchangeMatcher implements ServerWebExchangeMatcher {
|
||||
private final List<ServerWebExchangeMatcher> matchers;
|
||||
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Matches if the {@link PathPattern} matches the path within the application.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -22,14 +22,22 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* An interface for determining if a {@link ServerWebExchangeMatcher} matches.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ServerWebExchangeMatcher {
|
||||
|
||||
/**
|
||||
* Determines if a request matches or not
|
||||
* @param exchange
|
||||
* @return
|
||||
*/
|
||||
Mono<MatchResult> matches(ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* The result of matching
|
||||
*/
|
||||
class MatchResult {
|
||||
private final boolean match;
|
||||
private final Map<String, Object> variables;
|
||||
@ -43,18 +51,36 @@ public interface ServerWebExchangeMatcher {
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets potential variables and their values
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@link MatchResult} that is a match with no variables
|
||||
* @return
|
||||
*/
|
||||
public static Mono<MatchResult> match() {
|
||||
return match(Collections.emptyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates an instance of {@link MatchResult} that is a match with the specified variables
|
||||
* @param variables
|
||||
* @return
|
||||
*/
|
||||
public static Mono<MatchResult> match(Map<String, Object> variables) {
|
||||
return Mono.just(new MatchResult(true, variables));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@link MatchResult} that is not a match.
|
||||
* @return
|
||||
*/
|
||||
public static Mono<MatchResult> notMatch() {
|
||||
return Mono.just(new MatchResult(false, Collections.emptyMap()));
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.springframework.security.web.server.util.matcher;
|
||||
|
||||
/**
|
||||
* A rich object for associating a {@link ServerWebExchangeMatcher} to another object.
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
|
@ -23,11 +23,18 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides factory methods for creating common {@link ServerWebExchangeMatcher}
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class ServerWebExchangeMatchers {
|
||||
|
||||
/**
|
||||
* Creates a matcher that matches on the specific method and any of the provided patterns.
|
||||
* @param method the method to match on. If null, any method will be matched
|
||||
* @param patterns the patterns to match on
|
||||
* @return the matcher to use
|
||||
*/
|
||||
public static ServerWebExchangeMatcher pathMatchers(HttpMethod method, String... patterns) {
|
||||
List<ServerWebExchangeMatcher> matchers = new ArrayList<>(patterns.length);
|
||||
for (String pattern : patterns) {
|
||||
@ -36,15 +43,31 @@ public abstract class ServerWebExchangeMatchers {
|
||||
return new OrServerWebExchangeMatcher(matchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matcher that matches on any of the provided patterns.
|
||||
* @param patterns the patterns to match on
|
||||
* @return the matcher to use
|
||||
*/
|
||||
public static ServerWebExchangeMatcher pathMatchers(String... patterns) {
|
||||
return pathMatchers(null, patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matcher that will match on any of the provided matchers
|
||||
* @param matchers the matchers to match on
|
||||
* @return the matcher to use
|
||||
*/
|
||||
public static ServerWebExchangeMatcher matchers(ServerWebExchangeMatcher... matchers) {
|
||||
return new OrServerWebExchangeMatcher(matchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches any exchange
|
||||
* @return the matcher to use
|
||||
*/
|
||||
public static ServerWebExchangeMatcher anyExchange() {
|
||||
// we don't use a lambda to ensure a unique equals and hashcode
|
||||
// which otherwise can cause problems with adding multiple entries to an ordered LinkedHashMap
|
||||
return new ServerWebExchangeMatcher() {
|
||||
@Override
|
||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user