|
@@ -0,0 +1,1280 @@
|
|
|
+/*
|
|
|
+ * Copyright 2002-2013 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.
|
|
|
+ * You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ * See the License for the specific language governing permissions and
|
|
|
+ * limitations under the License.
|
|
|
+ */
|
|
|
+package org.springframework.security.config.annotation.web.builders;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import javax.servlet.Filter;
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+
|
|
|
+import org.springframework.security.authentication.AuthenticationManager;
|
|
|
+import org.springframework.security.authentication.AuthenticationProvider;
|
|
|
+import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
|
|
|
+import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|
|
+import org.springframework.security.config.annotation.SecurityBuilder;
|
|
|
+import org.springframework.security.config.annotation.SecurityConfigurer;
|
|
|
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
|
+import org.springframework.security.config.annotation.web.AbstractRequestMatcherConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.JeeConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.PortMapperConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.ServletApiConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.X509Configurer;
|
|
|
+import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
|
|
|
+import org.springframework.security.core.Authentication;
|
|
|
+import org.springframework.security.core.context.SecurityContext;
|
|
|
+import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
+import org.springframework.security.core.userdetails.UserDetailsService;
|
|
|
+import org.springframework.security.web.DefaultSecurityFilterChain;
|
|
|
+import org.springframework.security.web.PortMapper;
|
|
|
+import org.springframework.security.web.PortMapperImpl;
|
|
|
+import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
|
|
+import org.springframework.security.web.session.HttpSessionEventPublisher;
|
|
|
+import org.springframework.security.web.util.AntPathRequestMatcher;
|
|
|
+import org.springframework.security.web.util.AnyRequestMatcher;
|
|
|
+import org.springframework.security.web.util.RegexRequestMatcher;
|
|
|
+import org.springframework.security.web.util.RequestMatcher;
|
|
|
+import org.springframework.util.Assert;
|
|
|
+
|
|
|
+/**
|
|
|
+ * A {@link HttpSecurity} is similar to Spring Security's XML <http> element in the namespace
|
|
|
+ * configuration. It allows configuring web based security for specific http requests. By default
|
|
|
+ * it will be applied to all requests, but can be restricted using {@link #requestMatcher(RequestMatcher)}
|
|
|
+ * or other similar methods.
|
|
|
+ *
|
|
|
+ * <h2>Example Usage</h2>
|
|
|
+ *
|
|
|
+ * The most basic form based configuration can be seen below. The configuration will require that any URL
|
|
|
+ * that is requested will require a User with the role "ROLE_USER". It also defines an in memory authentication
|
|
|
+ * scheme with a user that has the username "user", the password "password", and the role "ROLE_USER". For
|
|
|
+ * additional examples, refer to the Java Doc of individual methods on {@link HttpSecurity}.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 3.2
|
|
|
+ * @see EnableWebSecurity
|
|
|
+ */
|
|
|
+public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain,HttpSecurity> implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
|
|
|
+ private AuthenticationManager authenticationManager;
|
|
|
+
|
|
|
+ private List<Filter> filters = new ArrayList<Filter>();
|
|
|
+ private RequestMatcher requestMatcher = new AnyRequestMatcher();
|
|
|
+ private FilterComparator comparitor = new FilterComparator();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Creates a new instance
|
|
|
+ * @param objectPostProcessor the {@link ObjectPostProcessor} that should be used
|
|
|
+ * @param authenticationBuilder the {@link AuthenticationManagerBuilder} to use for additional updates
|
|
|
+ * @param sharedObjects the shared Objects to initialize the {@link HttpSecurity} with
|
|
|
+ * @see WebSecurityConfiguration
|
|
|
+ */
|
|
|
+ public HttpSecurity(ObjectPostProcessor<Object> objectPostProcessor, AuthenticationManagerBuilder authenticationBuilder, Map<Class<Object>,Object> sharedObjects) {
|
|
|
+ super(objectPostProcessor);
|
|
|
+ Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null");
|
|
|
+ setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder);
|
|
|
+ for(Map.Entry<Class<Object>, Object> entry : sharedObjects.entrySet()) {
|
|
|
+ setSharedObject(entry.getKey(), entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring OpenID based authentication. Multiple invocations of
|
|
|
+ * {@link #openidLogin()} will override previous invocations.
|
|
|
+ *
|
|
|
+ * <h2>Example Configurations</h2>
|
|
|
+ *
|
|
|
+ * A basic example accepting the defaults and not using attribute exchange:
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .openidLogin()
|
|
|
+ * .permitAll();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * // the username must match the OpenID of the user you are
|
|
|
+ * // logging in with
|
|
|
+ * .withUser("https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * A more advanced example demonstrating using attribute exchange and
|
|
|
+ * providing a custom AuthenticationUserDetailsService that will make any
|
|
|
+ * user that authenticates a valid user.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .openidLogin()
|
|
|
+ * .loginPage("/login")
|
|
|
+ * .permitAll()
|
|
|
+ * .authenticationUserDetailsService(new AutoProvisioningUserDetailsService())
|
|
|
+ * .attributeExchange("https://www.google.com/.*")
|
|
|
+ * .attribute("email")
|
|
|
+ * .type("http://axschema.org/contact/email")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .attribute("firstname")
|
|
|
+ * .type("http://axschema.org/namePerson/first")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .attribute("lastname")
|
|
|
+ * .type("http://axschema.org/namePerson/last")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .and()
|
|
|
+ * .attributeExchange(".*yahoo.com.*")
|
|
|
+ * .attribute("email")
|
|
|
+ * .type("http://schema.openid.net/contact/email")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .attribute("fullname")
|
|
|
+ * .type("http://axschema.org/namePerson")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .and()
|
|
|
+ * .attributeExchange(".*myopenid.com.*")
|
|
|
+ * .attribute("email")
|
|
|
+ * .type("http://schema.openid.net/contact/email")
|
|
|
+ * .required(true)
|
|
|
+ * .and()
|
|
|
+ * .attribute("fullname")
|
|
|
+ * .type("http://schema.openid.net/namePerson")
|
|
|
+ * .required(true);
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * public class AutoProvisioningUserDetailsService implements
|
|
|
+ * AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
|
|
|
+ * public UserDetails loadUserDetails(OpenIDAuthenticationToken token) throws UsernameNotFoundException {
|
|
|
+ * return new User(token.getName(), "NOTUSED", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link OpenIDLoginConfigurer} for further customizations.
|
|
|
+ *
|
|
|
+ * @throws Exception
|
|
|
+ * @see OpenIDLoginConfigurer
|
|
|
+ */
|
|
|
+ public OpenIDLoginConfigurer<HttpSecurity> openidLogin() throws Exception {
|
|
|
+ return apply(new OpenIDLoginConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring of Session Management. Multiple invocations of
|
|
|
+ * {@link #sessionManagement()} will override previous invocations.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following configuration demonstrates how to enforce that only a
|
|
|
+ * single instance of a user is authenticated at a time. If a user
|
|
|
+ * authenticates with the username "user" without logging out and an attempt
|
|
|
+ * to authenticate with "user" is made the first session will be forcibly
|
|
|
+ * terminated and sent to the "/login?expired" URL.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class SessionManagementSecurityConfig extends
|
|
|
+ * WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .anyRequest().hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .permitAll()
|
|
|
+ * .and()
|
|
|
+ * .sessionManagement()
|
|
|
+ * .maximumSessions(1)
|
|
|
+ * .expiredUrl("/login?expired");
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth.
|
|
|
+ * inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * When using {@link SessionManagementConfigurer#maximumSessions(int)}, do
|
|
|
+ * not forget to configure {@link HttpSessionEventPublisher} for the
|
|
|
+ * application to ensure that expired sessions are cleaned up.
|
|
|
+ *
|
|
|
+ * In a web.xml this can be configured using the following:
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * <listener>
|
|
|
+ * <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
|
|
|
+ * </listener>
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * Alternatively,
|
|
|
+ * {@link AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher()}
|
|
|
+ * could return true.
|
|
|
+ *
|
|
|
+ * @return the {@link SessionManagementConfigurer} for further
|
|
|
+ * customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public SessionManagementConfigurer<HttpSecurity> sessionManagement() throws Exception {
|
|
|
+ return apply(new SessionManagementConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring a {@link PortMapper} that is available from
|
|
|
+ * {@link HttpSecurity#getSharedObject(Class)}. Other provided
|
|
|
+ * {@link SecurityConfigurer} objects use this configured
|
|
|
+ * {@link PortMapper} as a default {@link PortMapper} when redirecting from
|
|
|
+ * HTTP to HTTPS or from HTTPS to HTTP (for example when used in combination
|
|
|
+ * with {@link #requiresChannel()}. By default Spring Security uses a
|
|
|
+ * {@link PortMapperImpl} which maps the HTTP port 8080 to the HTTPS port
|
|
|
+ * 8443 and the HTTP port of 80 to the HTTPS port of 443.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following configuration will ensure that redirects within Spring
|
|
|
+ * Security from HTTP of a port of 9090 will redirect to HTTPS port of 9443
|
|
|
+ * and the HTTP port of 80 to the HTTPS port of 443.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class PortMapperSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .permitAll()
|
|
|
+ * .and()
|
|
|
+ * // Example portMapper() configuration
|
|
|
+ * .portMapper()
|
|
|
+ * .http(9090).mapsTo(9443)
|
|
|
+ * .http(80).mapsTo(443);
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link PortMapperConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ * @see {@link #requiresChannel()}
|
|
|
+ */
|
|
|
+ public PortMapperConfigurer<HttpSecurity> portMapper() throws Exception {
|
|
|
+ return apply(new PortMapperConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Configures container based based pre authentication. In this case,
|
|
|
+ * authentication is managed by the Servlet Container.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following configuration will use the principal found on the
|
|
|
+ * {@link HttpServletRequest} and if the user is in the role "ROLE_USER" or
|
|
|
+ * "ROLE_ADMIN" will add that to the resulting {@link Authentication}.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class JeeSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * // Example jee() configuration
|
|
|
+ * .jee()
|
|
|
+ * .mappableRoles("ROLE_USER", "ROLE_ADMIN");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * Developers wishing to use pre authentication with the container will need
|
|
|
+ * to ensure their web.xml configures the security constraints. For example,
|
|
|
+ * the web.xml (there is no equivalent Java based configuration supported by
|
|
|
+ * the Servlet specification) might look like:
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * <login-config>
|
|
|
+ * <auth-method>FORM</auth-method>
|
|
|
+ * <form-login-config>
|
|
|
+ * <form-login-page>/login</form-login-page>
|
|
|
+ * <form-error-page>/login?error</form-error-page>
|
|
|
+ * </form-login-config>
|
|
|
+ * </login-config>
|
|
|
+ *
|
|
|
+ * <security-role>
|
|
|
+ * <role-name>ROLE_USER</role-name>
|
|
|
+ * </security-role>
|
|
|
+ * <security-constraint>
|
|
|
+ * <web-resource-collection>
|
|
|
+ * <web-resource-name>Public</web-resource-name>
|
|
|
+ * <description>Matches unconstrained pages</description>
|
|
|
+ * <url-pattern>/login</url-pattern>
|
|
|
+ * <url-pattern>/logout</url-pattern>
|
|
|
+ * <url-pattern>/resources/*</url-pattern>
|
|
|
+ * </web-resource-collection>
|
|
|
+ * </security-constraint>
|
|
|
+ * <security-constraint>
|
|
|
+ * <web-resource-collection>
|
|
|
+ * <web-resource-name>Secured Areas</web-resource-name>
|
|
|
+ * <url-pattern>/*</url-pattern>
|
|
|
+ * </web-resource-collection>
|
|
|
+ * <auth-constraint>
|
|
|
+ * <role-name>ROLE_USER</role-name>
|
|
|
+ * </auth-constraint>
|
|
|
+ * </security-constraint>
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * Last you will need to configure your container to contain the user with the
|
|
|
+ * correct roles. This configuration is specific to the Servlet Container, so consult
|
|
|
+ * your Servlet Container's documentation.
|
|
|
+ *
|
|
|
+ * @return the {@link JeeConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public JeeConfigurer<HttpSecurity> jee() throws Exception {
|
|
|
+ return apply(new JeeConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Configures X509 based pre authentication.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following configuration will attempt to extract the username from
|
|
|
+ * the X509 certificate. Remember that the Servlet Container will need to be
|
|
|
+ * configured to request client certificates in order for this to work.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class X509SecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * // Example x509() configuration
|
|
|
+ * .x509();
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link X509Configurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public X509Configurer<HttpSecurity> x509() throws Exception {
|
|
|
+ return apply(new X509Configurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring of Remember Me authentication. Multiple invocations of
|
|
|
+ * {@link #rememberMe()} will override previous invocations.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following configuration demonstrates how to allow token based remember me
|
|
|
+ * authentication. Upon authenticating if the HTTP parameter named "remember-me" exists,
|
|
|
+ * then the user will be remembered even after their {@link javax.servlet.http.HttpSession} expires.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .permitAll()
|
|
|
+ * .and()
|
|
|
+ * // Example Remember Me Configuration
|
|
|
+ * .rememberMe();
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link RememberMeConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public RememberMeConfigurer<HttpSecurity> rememberMe() throws Exception {
|
|
|
+ return apply(new RememberMeConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows restricting access based upon the {@link HttpServletRequest} using
|
|
|
+ * {@link RequestMatcher} implementations (i.e. via URL patterns). Invoking
|
|
|
+ * {@link #authorizeUrls()} twice will override previous invocations of
|
|
|
+ * {@link #authorizeUrls()}.
|
|
|
+ *
|
|
|
+ * <h2>Example Configurations</h2>
|
|
|
+ *
|
|
|
+ * The most basic example is to configure all URLs to require the role "ROLE_USER". The
|
|
|
+ * configuration below requires authentication to every URL and will grant access to
|
|
|
+ * both the user "admin" and "user".
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER")
|
|
|
+ * .and()
|
|
|
+ * .withUser("adminr")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("ADMIN","USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * We can also configure multiple URLs. The configuration below requires authentication to every URL
|
|
|
+ * and will grant access to URLs starting with /admin/ to only the "admin" user. All other URLs either
|
|
|
+ * user can access.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/admin/**").hasRole("ADMIN")
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER")
|
|
|
+ * .and()
|
|
|
+ * .withUser("adminr")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("ADMIN","USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * Note that the matchers are considered in order. Therefore, the following is invalid because the first
|
|
|
+ * matcher matches every request and will never get to the second mapping:
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .antMatchers("/admin/**").hasRole("ADMIN")
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @see #requestMatcher(RequestMatcher)
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ExpressionUrlAuthorizationConfigurer<HttpSecurity> authorizeUrls() throws Exception {
|
|
|
+ return apply(new ExpressionUrlAuthorizationConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring the Request Cache. For example, a protected page (/protected) may be requested prior
|
|
|
+ * to authentication. The application will redirect the user to a login page. After authentication, Spring
|
|
|
+ * Security will redirect the user to the originally requested protected page (/protected). This is
|
|
|
+ * automatically applied when using {@link WebSecurityConfigurerAdapter}.
|
|
|
+ *
|
|
|
+ * @return the {@link RequestCacheConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public RequestCacheConfigurer<HttpSecurity> requestCache() throws Exception {
|
|
|
+ return apply(new RequestCacheConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring exception handling. This is automatically applied when using
|
|
|
+ * {@link WebSecurityConfigurerAdapter}.
|
|
|
+ *
|
|
|
+ * @return the {@link ExceptionHandlingConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling() throws Exception {
|
|
|
+ return apply(new ExceptionHandlingConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Sets up management of the {@link SecurityContext} on the
|
|
|
+ * {@link SecurityContextHolder} between {@link HttpServletRequest}'s. This is automatically
|
|
|
+ * applied when using {@link WebSecurityConfigurerAdapter}.
|
|
|
+ *
|
|
|
+ * @return the {@link SecurityContextConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public SecurityContextConfigurer<HttpSecurity> securityContext() throws Exception {
|
|
|
+ return apply(new SecurityContextConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Integrates the {@link HttpServletRequest} methods with the values found
|
|
|
+ * on the {@link SecurityContext}. This is automatically applied when using
|
|
|
+ * {@link WebSecurityConfigurerAdapter}.
|
|
|
+ *
|
|
|
+ * @return the {@link ServletApiConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ServletApiConfigurer<HttpSecurity> servletApi() throws Exception {
|
|
|
+ return apply(new ServletApiConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Provides logout support. This is automatically applied when using
|
|
|
+ * {@link WebSecurityConfigurerAdapter}. The default is that accessing
|
|
|
+ * the URL "/logout" will log the user out by invalidating the HTTP Session,
|
|
|
+ * cleaning up any {@link #rememberMe()} authentication that was configured,
|
|
|
+ * clearing the {@link SecurityContextHolder}, and then redirect to
|
|
|
+ * "/login?success".
|
|
|
+ *
|
|
|
+ * <h2>Example Custom Configuration</h2>
|
|
|
+ *
|
|
|
+ * The following customization to log out when the URL "/custom-logout" is
|
|
|
+ * invoked. Log out will remove the cookie named "remove", not invalidate the
|
|
|
+ * HttpSession, clear the SecurityContextHolder, and upon completion redirect
|
|
|
+ * to "/logout-success".
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class LogoutSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .and()
|
|
|
+ * // sample logout customization
|
|
|
+ * .logout()
|
|
|
+ * .logout()
|
|
|
+ * .deleteCookies("remove")
|
|
|
+ * .invalidateHttpSession(false)
|
|
|
+ * .logoutUrl("/custom-logout")
|
|
|
+ * .logoutSuccessUrl("/logout-success");
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public LogoutConfigurer<HttpSecurity> logout() throws Exception {
|
|
|
+ return apply(new LogoutConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring how an anonymous user is represented. This is automatically applied
|
|
|
+ * when used in conjunction with {@link WebSecurityConfigurerAdapter}. By default anonymous
|
|
|
+ * users will be represented with an {@link org.springframework.security.authentication.AnonymousAuthenticationToken} and contain the role
|
|
|
+ * "ROLE_ANONYMOUS".
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2
|
|
|
+ *
|
|
|
+ * The following configuration demonstrates how to specify that anonymous users should contain
|
|
|
+ * the role "ROLE_ANON" instead.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .and()
|
|
|
+ * // sample anonymous customization
|
|
|
+ * .anonymous()
|
|
|
+ * .authorities("ROLE_ANON");
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * The following demonstrates how to represent anonymous users as null. Note that this can cause
|
|
|
+ * {@link NullPointerException} in code that assumes anonymous authentication is enabled.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .and()
|
|
|
+ * // sample anonymous customization
|
|
|
+ * .anonymous()
|
|
|
+ * .disabled();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public AnonymousConfigurer<HttpSecurity> anonymous() throws Exception {
|
|
|
+ return apply(new AnonymousConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Specifies to support form based authentication. If
|
|
|
+ * {@link FormLoginConfigurer#loginPage(String)} is not specified a
|
|
|
+ * default login page will be generated.
|
|
|
+ *
|
|
|
+ * <h2>Example Configurations</h2>
|
|
|
+ *
|
|
|
+ * The most basic configuration defaults to automatically generating a login
|
|
|
+ * page at the URL "/login", redirecting to "/login?error" for
|
|
|
+ * authentication failure. The details of the login page can be found on
|
|
|
+ * {@link FormLoginConfigurer#loginPage(String)}
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * The configuration below demonstrates customizing the defaults.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .usernameParameter("j_username") // default is username
|
|
|
+ * .passwordParameter("j_password") // default is password
|
|
|
+ * .loginPage("/authentication/login") // default is /login with an HTTP get
|
|
|
+ * .failureUrl("/authentication/login?failed") // default is /login?error
|
|
|
+ * .loginProcessingUrl("/authentication/login/process"); // default is /login with an HTTP post
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @see FormLoginConfigurer#loginPage(String)
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
|
|
|
+ return apply(new FormLoginConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Configures channel security. In order for this configuration to be useful at least
|
|
|
+ * one mapping to a required channel must be provided. Invoking this method multiple times
|
|
|
+ * will reset previous invocations of the method.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The example below demonstrates how to require HTTPs for every request. Only requiring HTTPS
|
|
|
+ * for some requests is supported, but not recommended since an application that allows for HTTP
|
|
|
+ * introduces many security vulnerabilities. For one such example, read about
|
|
|
+ * <a href="http://en.wikipedia.org/wiki/Firesheep">Firesheep</a>.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class ChannelSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER")
|
|
|
+ * .and()
|
|
|
+ * .formLogin()
|
|
|
+ * .and()
|
|
|
+ * .channelSecurity()
|
|
|
+ * .anyRequest().requiresSecure();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * @return the {@link ChannelSecurityConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ChannelSecurityConfigurer<HttpSecurity> requiresChannel() throws Exception {
|
|
|
+ return apply(new ChannelSecurityConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Configures HTTP Basic authentication. Multiple infocations of
|
|
|
+ * {@link #httpBasic()} will override previous invocations.
|
|
|
+ *
|
|
|
+ * <h2>Example Configuration</h2>
|
|
|
+ *
|
|
|
+ * The example below demonstrates how to configure HTTP Basic authentication
|
|
|
+ * for an application. The default realm is "Spring Security Application",
|
|
|
+ * but can be customized using
|
|
|
+ * {@link HttpBasicConfigurer#realmName(String)}.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class HttpBasicSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER").and()
|
|
|
+ * .httpBasic();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link HttpBasicConfigurer} for further customizations
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public HttpBasicConfigurer<HttpSecurity> httpBasic() throws Exception {
|
|
|
+ return apply(new HttpBasicConfigurer<HttpSecurity>());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void beforeConfigure() throws Exception {
|
|
|
+ this.authenticationManager = getAuthenticationRegistry().build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected DefaultSecurityFilterChain performBuild() throws Exception {
|
|
|
+ Collections.sort(filters,comparitor);
|
|
|
+ return new DefaultSecurityFilterChain(requestMatcher, filters);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HttpSecurity authenticationProvider(AuthenticationProvider authenticationProvider) {
|
|
|
+ getAuthenticationRegistry().authenticationProvider(authenticationProvider);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#userDetailsService(org.springframework.security.core.userdetails.UserDetailsService)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HttpSecurity userDetailsService(UserDetailsService userDetailsService) throws Exception {
|
|
|
+ getAuthenticationRegistry().userDetailsService(userDetailsService);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ private AuthenticationManagerBuilder getAuthenticationRegistry() {
|
|
|
+ return getSharedObject(AuthenticationManagerBuilder.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilterAfter(javax.servlet.Filter, java.lang.Class)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
|
|
|
+ comparitor.registerAfter(filter.getClass(), afterFilter);
|
|
|
+ return addFilter(filter);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilterBefore(javax.servlet.Filter, java.lang.Class)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) {
|
|
|
+ comparitor.registerBefore(filter.getClass(), beforeFilter);
|
|
|
+ return addFilter(filter);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilter(javax.servlet.Filter)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HttpSecurity addFilter(Filter filter) {
|
|
|
+ Class<? extends Filter> filterClass = filter.getClass();
|
|
|
+ if(!comparitor.isRegistered(filterClass)) {
|
|
|
+ throw new IllegalArgumentException(
|
|
|
+ "The Filter class " + filterClass.getName()
|
|
|
+ + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
|
|
|
+ }
|
|
|
+ this.filters.add(filter);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows specifying which {@link HttpServletRequest} instances this
|
|
|
+ * {@link HttpSecurity} will be invoked on. This method allows for
|
|
|
+ * easily invoking the {@link HttpSecurity} for multiple
|
|
|
+ * different {@link RequestMatcher} instances. If only a single {@link RequestMatcher}
|
|
|
+ * is necessary consider using {@link #antMatcher(String)},
|
|
|
+ * {@link #regexMatcher(String)}, or {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * Invoking {@link #requestMatchers()} will override previous invocations of
|
|
|
+ * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)},
|
|
|
+ * and {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * <h3>Example Configurations</h3>
|
|
|
+ *
|
|
|
+ * The following configuration enables the {@link HttpSecurity} for URLs that
|
|
|
+ * begin with "/api/" or "/oauth/".
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .requestMatchers()
|
|
|
+ * .antMatchers("/api/**","/oauth/**")
|
|
|
+ * .and()
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER").and()
|
|
|
+ * .httpBasic();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * The configuration below is the same as the previous configuration.
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .requestMatchers()
|
|
|
+ * .antMatchers("/api/**")
|
|
|
+ * .antMatchers("/oauth/**")
|
|
|
+ * .and()
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER").and()
|
|
|
+ * .httpBasic();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * The configuration differs from the previous configurations because it invokes
|
|
|
+ * {@link #requestMatchers()} twice which resets the {@link RequestMatcherConfigurer}.
|
|
|
+ * Therefore the configuration below only matches on URLs that start with "/oauth/**".
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * @Configuration
|
|
|
+ * @EnableWebSecurity
|
|
|
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ * http
|
|
|
+ * .requestMatchers()
|
|
|
+ * .antMatchers("/api/**")
|
|
|
+ * .and()
|
|
|
+ * .requestMatchers()
|
|
|
+ * .antMatchers("/oauth/**")
|
|
|
+ * .and()
|
|
|
+ * .authorizeUrls()
|
|
|
+ * .antMatchers("/**").hasRole("USER").and()
|
|
|
+ * .httpBasic();
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * @Override
|
|
|
+ * protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
|
|
+ * throws Exception {
|
|
|
+ * auth
|
|
|
+ * .inMemoryAuthentication()
|
|
|
+ * .withUser("user")
|
|
|
+ * .password("password")
|
|
|
+ * .roles("USER");
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
+ * @return the {@link RequestMatcherConfigurer} for further customizations
|
|
|
+ */
|
|
|
+ public RequestMatcherConfigurer requestMatchers() {
|
|
|
+ return new RequestMatcherConfigurer();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring the {@link HttpSecurity} to only be invoked when
|
|
|
+ * matching the provided {@link RequestMatcher}. If more advanced configuration is
|
|
|
+ * necessary, consider using {@link #requestMatchers()}.
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * Invoking {@link #requestMatcher(RequestMatcher)} will override previous invocations of
|
|
|
+ * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)},
|
|
|
+ * and {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param requestMatcher the {@link RequestMatcher} to use (i.e. new AntPathRequestMatcher("/admin/**","GET") )
|
|
|
+ * @return the {@link HttpSecurity} for further customizations
|
|
|
+ * @see #requestMatchers()
|
|
|
+ * @see #antMatcher(String)
|
|
|
+ * @see #regexMatcher(String)
|
|
|
+ */
|
|
|
+ public HttpSecurity requestMatcher(RequestMatcher requestMatcher) {
|
|
|
+ this.requestMatcher = requestMatcher;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring the {@link HttpSecurity} to only be invoked when
|
|
|
+ * matching the provided ant pattern. If more advanced configuration is
|
|
|
+ * necessary, consider using {@link #requestMatchers()} or
|
|
|
+ * {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * Invoking {@link #antMatcher(String)} will override previous invocations of
|
|
|
+ * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)},
|
|
|
+ * and {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param antPattern the Ant Pattern to match on (i.e. "/admin/**")
|
|
|
+ * @return the {@link HttpSecurity} for further customizations
|
|
|
+ * @see AntPathRequestMatcher
|
|
|
+ */
|
|
|
+ public HttpSecurity antMatcher(String antPattern) {
|
|
|
+ return requestMatcher(new AntPathRequestMatcher(antPattern));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows configuring the {@link HttpSecurity} to only be invoked when
|
|
|
+ * matching the provided regex pattern. If more advanced configuration is
|
|
|
+ * necessary, consider using {@link #requestMatchers()} or
|
|
|
+ * {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * Invoking {@link #regexMatcher(String)} will override previous invocations of
|
|
|
+ * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)},
|
|
|
+ * and {@link #requestMatcher(RequestMatcher)}.
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param pattern the Regular Expression to match on (i.e. "/admin/.+")
|
|
|
+ * @return the {@link HttpSecurity} for further customizations
|
|
|
+ * @see RegexRequestMatcher
|
|
|
+ */
|
|
|
+ public HttpSecurity regexMatcher(String pattern) {
|
|
|
+ return requestMatcher(new RegexRequestMatcher(pattern, null));
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * (non-Javadoc)
|
|
|
+ * @see org.springframework.security.config.annotation.web.HttpBuilder#getAuthenticationManager()
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public AuthenticationManager getAuthenticationManager() {
|
|
|
+ return authenticationManager;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows mapping HTTP requests that this {@link HttpSecurity} will be used for
|
|
|
+ *
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 3.2
|
|
|
+ */
|
|
|
+ public final class RequestMatcherConfigurer extends AbstractRequestMatcherConfigurer<HttpSecurity,RequestMatcherConfigurer,DefaultSecurityFilterChain> {
|
|
|
+
|
|
|
+ protected RequestMatcherConfigurer chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
|
|
+ requestMatcher(new OrRequestMatcher(requestMatchers));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return the {@link HttpSecurity} for further customizations
|
|
|
+ *
|
|
|
+ * @return the {@link HttpSecurity} for further customizations
|
|
|
+ */
|
|
|
+ public HttpSecurity and() {
|
|
|
+ return HttpSecurity.this;
|
|
|
+ }
|
|
|
+
|
|
|
+ private RequestMatcherConfigurer(){}
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Internal {@link RequestMatcher} instance used by {@link RequestMatcher}
|
|
|
+ * that will match if any of the passed in {@link RequestMatcher} instances
|
|
|
+ * match.
|
|
|
+ *
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 3.2
|
|
|
+ */
|
|
|
+ private static final class OrRequestMatcher implements RequestMatcher {
|
|
|
+ private final List<RequestMatcher> requestMatchers;
|
|
|
+
|
|
|
+ private OrRequestMatcher(List<RequestMatcher> requestMatchers) {
|
|
|
+ this.requestMatchers = requestMatchers;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean matches(HttpServletRequest request) {
|
|
|
+ for(RequestMatcher matcher : requestMatchers) {
|
|
|
+ if(matcher.matches(request)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|