HttpSecurity
是Spring Security Config
用于配置http
请求安全控制的安全构建器(类似于Spring Security XML
配置中的http
命名空间配置部分),它的构建目标是一个SecurityFilterChain
,实现类使用DefaultSecurityFilterChain
。该目标SecurityFilterChain
最终会被Spring Security
的安全过滤器FilterChainProxy
所持有和应用于相应的http
请求的安全控制。
HttpSecurity
缺省情况下应用到所有的请求,不过也可通过使用其方法#requestMatcher(RequestMatcher)
(或者其他类似的手段)限制它仅应用到某些请求上。
安全构建器HttpSecurity
和WebSecurity
的区别是 :
WebSecurity
不仅通过HttpSecurity
定义某些请求的安全控制,也通过其他方式定义其他某些请求可以忽略安全控制;HttpSecurity
仅用于定义需要安全控制的请求(当然HttpSecurity
也可以指定某些请求不需要安全控制);- 可以认为
HttpSecurity
是WebSecurity
的一部分,WebSecurity
是包含HttpSecurity
的更大的一个概念;注意 : 这里是从语义上讲,而不是从实现层面的表示形式上讲;
- 构建目标不同
WebSecurity
构建目标是整个Spring Security
安全过滤器FilterChainProxy
,- 而
HttpSecurity
的构建目标仅仅是FilterChainProxy
中的一个SecurityFilterChain
。
一个HttpSecurity
使用的例子 :
@Configuration
@EnableWebSecurity
public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
源代码
源代码版本 Spring Security Config 5.1.4.RELEASE
package org.springframework.security.config.annotation.web.builders;
// 省略 imports 行
/**
*
* @author Rob Winch
* @author Joe Grandja
* @since 3.2
* @see EnableWebSecurity
*/
public final class HttpSecurity extends
AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
implements SecurityBuilder<DefaultSecurityFilterChain>,
HttpSecurityBuilder<HttpSecurity> {
private final RequestMatcherConfigurer requestMatcherConfigurer;
private List<Filter> filters = new ArrayList<>();
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
private FilterComparator comparator = new FilterComparator();
/**
* Creates a new instance
* @param objectPostProcessor the ObjectPostProcessor that should be used
* @param authenticationBuilder the AuthenticationManagerBuilder to use for
* additional updates
* @param sharedObjects the shared Objects to initialize the HttpSecurity with
* @see WebSecurityConfiguration
*/
@SuppressWarnings("unchecked")
public HttpSecurity(ObjectPostProcessor<Object> objectPostProcessor,
AuthenticationManagerBuilder authenticationBuilder,
Map<Class<? extends Object>, Object> sharedObjects) {
super(objectPostProcessor);
Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null");
setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder);
for (Map.Entry<Class<? extends Object>, Object> entry : sharedObjects
.entrySet()) {
setSharedObject((Class<Object>) entry.getKey(), entry.getValue());
}
ApplicationContext context = (ApplicationContext) sharedObjects
.get(ApplicationContext.class);
this.requestMatcherConfigurer = new RequestMatcherConfigurer(context);
}
private ApplicationContext getContext() {
return getSharedObject(ApplicationContext.class);
}
/**
* Allows configuring OpenID based authentication.
*
*
* @return the OpenIDLoginConfigurer for further customizations.
*
* @throws Exception
* @see OpenIDLoginConfigurer
*/
public OpenIDLoginConfigurer<HttpSecurity> openidLogin() throws Exception {
return getOrApply(new OpenIDLoginConfigurer<>());
}
/**
* Adds the Security headers to the response. This is activated by default when using
* WebSecurityConfigurerAdapter's default constructor. Accepting the
* default provided by WebSecurityConfigurerAdapter or only invoking
* #headers() without invoking additional methods on it
*/
public HeadersConfigurer<HttpSecurity> headers() throws Exception {
return getOrApply(new HeadersConfigurer<>());
}
/**
* Adds a CorsFilter to be used. If a bean by the name of corsFilter is
* provided, that CorsFilter is used. Else if corsConfigurationSource is
* defined, then that CorsConfiguration is used. Otherwise, if Spring MVC is
* on the classpath a HandlerMappingIntrospector is used.
*
* @return the CorsConfigurer for customizations
* @throws Exception
*/
public CorsConfigurer<HttpSecurity> cors() throws Exception {
return getOrApply(new CorsConfigurer<>());
}
/**
* Allows configuring of Session Management.
*
* When using SessionManagementConfigurer#maximumSessions(int), do not forget
* to configure HttpSessionEventPublisher for the application to ensure that
* expired sessions are cleaned up.
*
*
* @return the SessionManagementConfigurer for further customizations
* @throws Exception
*/
public SessionManagementConfigurer<HttpSecurity> sessionManagement() throws Exception {
return getOrApply(new SessionManagementConfigurer<>());
}
/**
* Allows configuring a PortMapper that is available from
* HttpSecurity#getSharedObject(Class). Other provided
* SecurityConfigurer objects use this configured PortMapper as a
* default PortMapper when redirecting from HTTP to HTTPS or from HTTPS to
* HTTP (for example when used in combination with #requiresChannel(). By
* default Spring Security uses a PortMapperImpl which maps the HTTP port 8080
* to the HTTPS port 8443 and the HTTP port of 80 to the HTTPS port of 443.
*
*
* @return the PortMapperConfigurer for further customizations
* @throws Exception
* @see #requiresChannel()
*/
public PortMapperConfigurer<HttpSecurity> portMapper() throws Exception {
return getOrApply(new PortMapperConfigurer<>());
}
/**
* Configures container based pre authentication. In this case, authentication
* is managed by the Servlet Container.
*
*
* @return the JeeConfigurer for further customizations
* @throws Exception
*/
public JeeConfigurer<HttpSecurity> jee() throws Exception {
return getOrApply(new JeeConfigurer<>());
}
/**
* Configures X509 based pre authentication.
*
*
* @return the X509Configurer for further customizations
* @throws Exception
*/
public X509Configurer<HttpSecurity> x509() throws Exception {
return getOrApply(new X509Configurer<>());
}
/**
* Allows configuring of Remember Me authentication.
*
*
* @return the RememberMeConfigurer for further customizations
* @throws Exception
*/
public RememberMeConfigurer<HttpSecurity> rememberMe() throws Exception {
return getOrApply(new RememberMeConfigurer<>());
}
/**
* Allows restricting access based upon the HttpServletRequest using
*
*
*
* @see #requestMatcher(RequestMatcher)
*
* @return the ExpressionUrlAuthorizationConfigurer for further customizations
* @throws Exception
*/
public ExpressionUrlAuthorizationConfigurer<HttpSecurity>.
ExpressionInterceptUrlRegistry authorizeRequests()
throws Exception {
ApplicationContext context = getContext();
return getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context))
.getRegistry();
}
/**
* 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 WebSecurityConfigurerAdapter.
*
* @return the RequestCacheConfigurer for further customizations
* @throws Exception
*/
public RequestCacheConfigurer<HttpSecurity> requestCache() throws Exception {
return getOrApply(new RequestCacheConfigurer<>());
}
/**
* Allows configuring exception handling. This is automatically applied when using
* WebSecurityConfigurerAdapter.
*
* @return the ExceptionHandlingConfigurer for further customizations
* @throws Exception
*/
public ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling() throws Exception {
return getOrApply(new ExceptionHandlingConfigurer<>());
}
/**
* Sets up management of the SecurityContext on the
* SecurityContextHolder between HttpServletRequest's. This is
* automatically applied when using WebSecurityConfigurerAdapter.
*
* @return the SecurityContextConfigurer for further customizations
* @throws Exception
*/
public SecurityContextConfigurer<HttpSecurity> securityContext() throws Exception {
return getOrApply(new SecurityContextConfigurer<>());
}
/**
* Integrates the HttpServletRequest methods with the values found on the
* SecurityContext. This is automatically applied when using
* WebSecurityConfigurerAdapter.
*
* @return the ServletApiConfigurer for further customizations
* @throws Exception
*/
public ServletApiConfigurer<HttpSecurity> servletApi() throws Exception {
return getOrApply(new ServletApiConfigurer<>());
}
/**
* Adds CSRF support. This is activated by default when using
* WebSecurityConfigurerAdapter's default constructor.
*
*
* @return the ServletApiConfigurer for further customizations
* @throws Exception
*/
public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
ApplicationContext context = getContext();
return getOrApply(new CsrfConfigurer<>(context));
}
/**
* Provides logout support. This is automatically applied when using
* WebSecurityConfigurerAdapter. The default is that accessing the URL
* "/logout" will log the user out by invalidating the HTTP Session, cleaning up any
* #rememberMe() authentication that was configured, clearing the
* SecurityContextHolder, and then redirect to "/login?success".
*
*
* @return the LogoutConfigurer for further customizations
* @throws Exception
*/
public LogoutConfigurer<HttpSecurity> logout() throws Exception {
return getOrApply(new LogoutConfigurer<>());
}
/**
* Allows configuring how an anonymous user is represented. This is automatically
* applied when used in conjunction with WebSecurityConfigurerAdapter. By
* default anonymous users will be represented with an
* org.springframework.security.authentication.AnonymousAuthenticationToken
* and contain the role "ROLE_ANONYMOUS".
*
* @return the AnonymousConfigurer for further customizations
* @throws Exception
*/
public AnonymousConfigurer<HttpSecurity> anonymous() throws Exception {
return getOrApply(new AnonymousConfigurer<>());
}
/**
* Specifies to support form based authentication. If
* FormLoginConfigurer#loginPage(String) is not specified a default login page
* will be generated.
*
*
* @see FormLoginConfigurer#loginPage(String)
*
* @return the FormLoginConfigurer for further customizations
* @throws Exception
*/
public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
return getOrApply(new FormLoginConfigurer<>());
}
/**
* Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
*
* @return the OAuth2LoginConfigurer for further customizations
* @throws Exception
*/
public OAuth2LoginConfigurer<HttpSecurity> oauth2Login() throws Exception {
return getOrApply(new OAuth2LoginConfigurer<>());
}
/**
* Configures OAuth 2.0 Client support.
*
* @since 5.1
* @return the OAuth2ClientConfigurer for further customizations
* @throws Exception
*/
public OAuth2ClientConfigurer<HttpSecurity> oauth2Client() throws Exception {
OAuth2ClientConfigurer<HttpSecurity> configurer = getOrApply(new OAuth2ClientConfigurer<>());
this.postProcess(configurer);
return configurer;
}
/**
* Configures OAuth 2.0 Resource Server support.
*
* @since 5.1
* @return the OAuth2ResourceServerConfigurer for further customizations
* @throws Exception
*/
public OAuth2ResourceServerConfigurer<HttpSecurity> oauth2ResourceServer() throws Exception {
OAuth2ResourceServerConfigurer<HttpSecurity> configurer =
getOrApply(new OAuth2ResourceServerConfigurer<>(getContext()));
this.postProcess(configurer);
return configurer;
}
/**
* Configures channel security. In order for this configuration to be useful at least
* one mapping to a required channel must be provided.
*
*
* @return the ChannelSecurityConfigurer for further customizations
* @throws Exception
*/
public ChannelSecurityConfigurer<HttpSecurity>.ChannelRequestMatcherRegistry requiresChannel()
throws Exception {
ApplicationContext context = getContext();
return getOrApply(new ChannelSecurityConfigurer<>(context))
.getRegistry();
}
/**
* Configures HTTP Basic authentication.
*
*
* @return the HttpBasicConfigurer for further customizations
* @throws Exception
*/
public HttpBasicConfigurer<HttpSecurity> httpBasic() throws Exception {
return getOrApply(new HttpBasicConfigurer<>());
}
public <C> void setSharedObject(Class<C> sharedType, C object) {
super.setSharedObject(sharedType, object);
}
@Override
protected void beforeConfigure() throws Exception {
setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build());
}
@Override
protected DefaultSecurityFilterChain performBuild() throws Exception {
Collections.sort(filters, comparator);
return new DefaultSecurityFilterChain(requestMatcher, filters);
}
/*
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#authenticationProvider
* (org.springframework.security.authentication.AuthenticationProvider)
*/
public HttpSecurity authenticationProvider(
AuthenticationProvider authenticationProvider) {
getAuthenticationRegistry().authenticationProvider(authenticationProvider);
return this;
}
/*
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#userDetailsService
* (org.springframework.security.core.userdetails.UserDetailsService)
*/
public HttpSecurity userDetailsService(UserDetailsService userDetailsService)
throws Exception {
getAuthenticationRegistry().userDetailsService(userDetailsService);
return this;
}
private AuthenticationManagerBuilder getAuthenticationRegistry() {
return getSharedObject(AuthenticationManagerBuilder.class);
}
/*
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilterAfter(javax
* .servlet.Filter, java.lang.Class)
*/
public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
comparator.registerAfter(filter.getClass(), afterFilter);
return addFilter(filter);
}
/*
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilterBefore(
* javax.servlet.Filter, java.lang.Class)
*/
public HttpSecurity addFilterBefore(Filter filter,
Class<? extends Filter> beforeFilter) {
comparator.registerBefore(filter.getClass(), beforeFilter);
return addFilter(filter);
}
/*
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilter(javax.
* servlet.Filter)
*/
public HttpSecurity addFilter(Filter filter) {
Class<? extends Filter> filterClass = filter.getClass();
if (!comparator.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;
}
/**
* Adds the Filter at the location of the specified Filter class. For example, if you
* want the filter CustomFilter to be registered in the same position as
* UsernamePasswordAuthenticationFilter, you can invoke:
*
*
* addFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
*
*
* Registration of multiple Filters in the same location means their ordering is not
* deterministic. More concretely, registering multiple Filters in the same location
* does not override existing Filters. Instead, do not register Filters you do not
* want to use.
*
* @param filter the Filter to register
* @param atFilter the location of another Filter that is already registered
* (i.e. known) with Spring Security.
* @return the HttpSecurity for further customizations
*/
public HttpSecurity addFilterAt(Filter filter, Class<? extends Filter> atFilter) {
this.comparator.registerAt(filter.getClass(), atFilter);
return addFilter(filter);
}
/**
* Allows specifying which HttpServletRequest instances this
* HttpSecurity will be invoked on. This method allows for easily invoking the
* HttpSecurity for multiple different RequestMatcher instances. If
* only a single RequestMatcher is necessary consider using #mvcMatcher(String),
* #antMatcher(String), #regexMatcher(String), or
* #requestMatcher(RequestMatcher).
*
*
* Invoking #requestMatchers() will not override previous invocations of #mvcMatcher(String),
* #requestMatchers(), #antMatcher(String),
* #regexMatcher(String), and requestMatcher(RequestMatcher).
*
*
*
* @return the RequestMatcherConfigurer for further customizations
*/
public RequestMatcherConfigurer requestMatchers() {
return requestMatcherConfigurer;
}
/**
* Allows configuring the HttpSecurity to only be invoked when matching the
* provided RequestMatcher. If more advanced configuration is necessary,
* consider using #requestMatchers().
*
*
* Invoking #requestMatcher(RequestMatcher) will override previous invocations
* of #requestMatchers(), #mvcMatcher(String), #antMatcher(String),
* #regexMatcher(String), and #requestMatcher(RequestMatcher).
*
*
* @param requestMatcher the RequestMatcher to use (i.e. new
* AntPathRequestMatcher("/admin/**","GET") )
* @return the HttpSecurity or further customizations
* @see #requestMatchers()
* @see #antMatcher(String)
* @see #regexMatcher(String)
*/
public HttpSecurity requestMatcher(RequestMatcher requestMatcher) {
this.requestMatcher = requestMatcher;
return this;
}
/**
* Allows configuring the HttpSecurity to only be invoked when matching the
* provided ant pattern. If more advanced configuration is necessary, consider using
* #requestMatchers() or #requestMatcher(RequestMatcher).
*
*
* Invoking #antMatcher(String) will override previous invocations of #mvcMatcher(String),
* #requestMatchers(), #antMatcher(String),
* #regexMatcher(String), and #requestMatcher(RequestMatcher).
*
*
* @param antPattern the Ant Pattern to match on (i.e. "/admin/**")
* @return the HttpSecurity for further customizations
* @see AntPathRequestMatcher
*/
public HttpSecurity antMatcher(String antPattern) {
return requestMatcher(new AntPathRequestMatcher(antPattern));
}
/**
* Allows configuring the HttpSecurity to only be invoked when matching the
* provided Spring MVC pattern. If more advanced configuration is necessary, consider using
* #requestMatchers() or #requestMatcher(RequestMatcher).
*
*
* Invoking #mvcMatcher(String) will override previous invocations of #mvcMatcher(String),
* #requestMatchers(), #antMatcher(String),
* #regexMatcher(String), and #requestMatcher(RequestMatcher).
*
*
* @param mvcPattern the Spring MVC Pattern to match on (i.e. "/admin/**")
* @return the HttpSecurity for further customizations
* @see MvcRequestMatcher
*/
public HttpSecurity mvcMatcher(String mvcPattern) {
HandlerMappingIntrospector introspector = new HandlerMappingIntrospector(getContext());
return requestMatcher(new MvcRequestMatcher(introspector, mvcPattern));
}
/**
* Allows configuring the HttpSecurity to only be invoked when matching the
* provided regex pattern. If more advanced configuration is necessary, consider using
* #requestMatchers() or #requestMatcher(RequestMatcher).
*
*
* Invoking #regexMatcher(String) will override previous invocations of #mvcMatcher(String),
* #requestMatchers(), #antMatcher(String),
* #regexMatcher(String), and #requestMatcher(RequestMatcher).
*
*
* @param pattern the Regular Expression to match on (i.e. "/admin/.+")
* @return the HttpSecurity for further customizations
* @see RegexRequestMatcher
*/
public HttpSecurity regexMatcher(String pattern) {
return requestMatcher(new RegexRequestMatcher(pattern, null));
}
/**
* An extension to RequestMatcherConfigurer that allows optionally configuring
* the servlet path.
*
* @author Rob Winch
*/
public final class MvcMatchersRequestMatcherConfigurer extends RequestMatcherConfigurer {
/**
* Creates a new instance
* @param context the ApplicationContext to use
* @param matchers the MvcRequestMatcher instances to set the servlet path
* on if #servletPath(String) is set.
*/
private MvcMatchersRequestMatcherConfigurer(ApplicationContext context,
List<MvcRequestMatcher> matchers) {
super(context);
this.matchers = new ArrayList<>(matchers);
}
public RequestMatcherConfigurer servletPath(String servletPath) {
for (RequestMatcher matcher : this.matchers) {
((MvcRequestMatcher) matcher).setServletPath(servletPath);
}
return this;
}
}
/**
* Allows mapping HTTP requests that this HttpSecurity will be used for
*
* @author Rob Winch
* @since 3.2
*/
public class RequestMatcherConfigurer
extends AbstractRequestMatcherRegistry<RequestMatcherConfigurer> {
protected List<RequestMatcher> matchers = new ArrayList<>();
/**
* @param context
*/
private RequestMatcherConfigurer(ApplicationContext context) {
setApplicationContext(context);
}
@Override
public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method,
String... mvcPatterns) {
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
setMatchers(mvcMatchers);
return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers);
}
@Override
public MvcMatchersRequestMatcherConfigurer mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@Override
protected RequestMatcherConfigurer chainRequestMatchers(
List<RequestMatcher> requestMatchers) {
setMatchers(requestMatchers);
return this;
}
private void setMatchers(List<? extends RequestMatcher> requestMatchers) {
this.matchers.addAll(requestMatchers);
requestMatcher(new OrRequestMatcher(this.matchers));
}
/**
* Return the HttpSecurity for further customizations
*
* @return the HttpSecurity for further customizations
*/
public HttpSecurity and() {
return HttpSecurity.this;
}
}
/**
* If the SecurityConfigurer has already been specified get the original,
* otherwise apply the new SecurityConfigurerAdapter.
*
* @param configurer the SecurityConfigurer to apply if one is not found for
* this SecurityConfigurer class.
* @return the current SecurityConfigurer for the configurer passed in
* @throws Exception
*/
@SuppressWarnings("unchecked")
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>>
C getOrApply(C configurer) throws Exception {
C existingConfig = (C) getConfigurer(configurer.getClass());
if (existingConfig != null) {
return existingConfig;
}
return apply(configurer);
}
}
参考文章
Spring Security : 配置 HttpSecurity 的 SecurityConfigurer
Spring Security : 安全构建器HttpSecurity和WebSecurity的区别
Spring Security : Web安全构建器 WebSecurity