|
@@ -15,7 +15,9 @@
|
|
|
*/
|
|
|
package org.springframework.security.config.web.server;
|
|
|
|
|
|
+import java.time.Duration;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.List;
|
|
|
import java.util.Optional;
|
|
|
|
|
@@ -24,8 +26,13 @@ import org.springframework.security.authorization.AuthenticatedAuthorizationMana
|
|
|
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
|
|
import org.springframework.security.authorization.AuthorizationDecision;
|
|
|
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|
|
+import org.springframework.security.web.server.AuthenticationEntryPoint;
|
|
|
+import org.springframework.security.web.server.HttpBasicAuthenticationConverter;
|
|
|
import org.springframework.security.web.server.MatcherSecurityWebFilterChain;
|
|
|
import org.springframework.security.web.server.SecurityWebFilterChain;
|
|
|
+import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
|
|
|
+import org.springframework.security.web.server.authentication.DefaultAuthenticationSuccessHandler;
|
|
|
+import org.springframework.security.web.server.authentication.www.HttpBasicAuthenticationEntryPoint;
|
|
|
import org.springframework.security.web.server.authorization.AuthorizationContext;
|
|
|
import org.springframework.security.web.server.authorization.AuthorizationWebFilter;
|
|
|
import org.springframework.security.web.server.authorization.DelegatingReactiveAuthorizationManager;
|
|
@@ -33,6 +40,14 @@ import org.springframework.security.web.server.context.AuthenticationReactorCont
|
|
|
import org.springframework.security.web.server.context.SecurityContextRepositoryWebFilter;
|
|
|
import org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter;
|
|
|
import org.springframework.security.web.server.context.SecurityContextRepository;
|
|
|
+import org.springframework.security.web.server.header.CacheControlHttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.CompositeHttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.ContentTypeOptionsHttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.HttpHeaderWriterWebFilter;
|
|
|
+import org.springframework.security.web.server.header.HttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.StrictTransportSecurityHttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.XFrameOptionsHttpHeadersWriter;
|
|
|
+import org.springframework.security.web.server.header.XXssProtectionHttpHeadersWriter;
|
|
|
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
|
|
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcherEntry;
|
|
|
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
|
|
@@ -209,4 +224,147 @@ public class HttpSecurity {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 5.0
|
|
|
+ */
|
|
|
+ public class HttpBasicBuilder {
|
|
|
+ private ReactiveAuthenticationManager authenticationManager;
|
|
|
+
|
|
|
+ private SecurityContextRepository securityContextRepository;
|
|
|
+
|
|
|
+ private AuthenticationEntryPoint entryPoint = new HttpBasicAuthenticationEntryPoint();
|
|
|
+
|
|
|
+ public HttpBasicBuilder authenticationManager(ReactiveAuthenticationManager authenticationManager) {
|
|
|
+ this.authenticationManager = authenticationManager;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public HttpBasicBuilder securityContextRepository(SecurityContextRepository securityContextRepository) {
|
|
|
+ this.securityContextRepository = securityContextRepository;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public HttpSecurity and() {
|
|
|
+ return HttpSecurity.this;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected AuthenticationWebFilter build() {
|
|
|
+ AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(authenticationManager);
|
|
|
+ authenticationFilter.setEntryPoint(entryPoint);
|
|
|
+ authenticationFilter.setAuthenticationConverter(new HttpBasicAuthenticationConverter());
|
|
|
+ if(securityContextRepository != null) {
|
|
|
+ DefaultAuthenticationSuccessHandler handler = new DefaultAuthenticationSuccessHandler();
|
|
|
+ handler.setSecurityContextRepository(securityContextRepository);
|
|
|
+ authenticationFilter.setAuthenticationSuccessHandler(handler);
|
|
|
+ }
|
|
|
+ return authenticationFilter;
|
|
|
+ }
|
|
|
+
|
|
|
+ private HttpBasicBuilder() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 5.0
|
|
|
+ */
|
|
|
+ public class HeaderBuilder {
|
|
|
+ private final List<HttpHeadersWriter> writers;
|
|
|
+
|
|
|
+ private CacheControlHttpHeadersWriter cacheControl = new CacheControlHttpHeadersWriter();
|
|
|
+
|
|
|
+ private ContentTypeOptionsHttpHeadersWriter contentTypeOptions = new ContentTypeOptionsHttpHeadersWriter();
|
|
|
+
|
|
|
+ private StrictTransportSecurityHttpHeadersWriter hsts = new StrictTransportSecurityHttpHeadersWriter();
|
|
|
+
|
|
|
+ private XFrameOptionsHttpHeadersWriter frameOptions = new XFrameOptionsHttpHeadersWriter();
|
|
|
+
|
|
|
+ private XXssProtectionHttpHeadersWriter xss = new XXssProtectionHttpHeadersWriter();
|
|
|
+
|
|
|
+ public HttpSecurity and() {
|
|
|
+ return HttpSecurity.this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CacheSpec cache() {
|
|
|
+ return new CacheSpec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public ContentTypeOptionsSpec contentTypeOptions() {
|
|
|
+ return new ContentTypeOptionsSpec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public FrameOptionsSpec frameOptions() {
|
|
|
+ return new FrameOptionsSpec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public HstsSpec hsts() {
|
|
|
+ return new HstsSpec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public HttpHeaderWriterWebFilter build() {
|
|
|
+ HttpHeadersWriter writer = new CompositeHttpHeadersWriter(writers);
|
|
|
+ return new HttpHeaderWriterWebFilter(writer);
|
|
|
+ }
|
|
|
+
|
|
|
+ public XssProtectionSpec xssProtection() {
|
|
|
+ return new XssProtectionSpec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public class CacheSpec {
|
|
|
+ public void disable() {
|
|
|
+ writers.remove(cacheControl);
|
|
|
+ }
|
|
|
+
|
|
|
+ private CacheSpec() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ContentTypeOptionsSpec {
|
|
|
+ public void disable() {
|
|
|
+ writers.remove(contentTypeOptions);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ContentTypeOptionsSpec() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ public class FrameOptionsSpec {
|
|
|
+ public void mode(XFrameOptionsHttpHeadersWriter.Mode mode) {
|
|
|
+ frameOptions.setMode(mode);
|
|
|
+ }
|
|
|
+ public void disable() {
|
|
|
+ writers.remove(frameOptions);
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameOptionsSpec() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ public class HstsSpec {
|
|
|
+ public void maxAge(Duration maxAge) {
|
|
|
+ hsts.setMaxAge(maxAge);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void includeSubdomains(boolean includeSubDomains) {
|
|
|
+ hsts.setIncludeSubDomains(includeSubDomains);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void disable() {
|
|
|
+ writers.remove(hsts);
|
|
|
+ }
|
|
|
+
|
|
|
+ private HstsSpec() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ public class XssProtectionSpec {
|
|
|
+ public void disable() {
|
|
|
+ writers.remove(xss);
|
|
|
+ }
|
|
|
+
|
|
|
+ private XssProtectionSpec() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ private HeaderBuilder() {
|
|
|
+ this.writers = new ArrayList<>(
|
|
|
+ Arrays.asList(cacheControl, contentTypeOptions, hsts, frameOptions, xss));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|