5. Java Configuration
在 Spring 3.1 中,对Java Configuration的常规支持已添加到 Spring Framework 中。从 Spring Security 3.2 开始,Spring Security Java Configuration 支持使用户可以轻松配置 Spring Security,而无需使用任何 XML。
如果您熟悉第 6 章,安全命名空间配置,则应该在第 6 章,安全命名空间配置和 Security Java Configuration 支持之间找到很多相似之处。
Note
Spring Security 提供了许多示例应用程序,它们演示了 Spring Security Java 配置的使用。
5.1 Hello Web Security Java 配置
第一步是创建我们的 Spring Security Java 配置。该配置将创建一个称为springSecurityFilterChain
的 Servlet 过滤器,该过滤器负责应用程序中的所有安全性(保护应用程序 URL,验证提交的用户名和密码,重定向到登录表单等)。您可以在下面找到 Spring Security Java 配置的最基本示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build());
return manager;
}
}
此配置的确没有太多,但是它做了很多。您可以找到以下功能的摘要:
-
要求对应用程序中的每个 URL 进行身份验证
-
为您生成一个登录表单
-
允许具有 Username * user *和 Password * password *的用户使用基于表单的身份验证进行身份验证
-
允许用户注销
-
CSRF attack prevention
-
Session Fixation protection
-
安全标题集成
-
HTTP 严格传输安全安全请求
-
X-Content-Type-Options integration
-
缓存控制(以后可以由您的应用程序覆盖以允许缓存您的静态资源)
-
X-XSS-Protection integration
-
X-Frame-Options 集成有助于防止Clickjacking
-
-
与以下 Servlet API 方法集成
5.1.1 AbstractSecurityWebApplicationInitializer
下一步是向 War 注册springSecurityFilterChain
。可以在 Servlet 3.0 环境中使用Spring 的 WebApplicationInitializer 支持在 Java 配置中完成此操作。毫不奇怪,Spring Security 提供了一个 Base ClassAbstractSecurityWebApplicationInitializer
,它将确保springSecurityFilterChain
为您注册。使用AbstractSecurityWebApplicationInitializer
的方式因我们是否已经在使用 Spring 或 Spring Security 是应用程序中唯一的 Spring 组件而异。
-
第 5.1.2 节“不存在 Spring 的 AbstractSecurityWebApplicationInitializer”-如果您尚未使用 Spring,请按照以下说明进行操作
-
第 5.1.3 节“带有 Spring MVC 的 AbstractSecurityWebApplicationInitializer”-如果您已经在使用 Spring,请按照以下说明进行操作
5.1.2 不存在 Spring 的 AbstractSecurityWebApplicationInitializer
如果您不使用 Spring 或 Spring MVC,则需要将WebSecurityConfig
传递到超类中,以确保配置被接受。您可以在下面找到一个示例:
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(WebSecurityConfig.class);
}
}
SecurityWebApplicationInitializer
将执行以下操作:
-
为应用程序中的每个 URL 自动注册 springSecurityFilterChain 过滤器
-
添加一个加载WebSecurityConfig的 ContextLoaderListener。
5.1.3 使用 Spring MVC 的 AbstractSecurityWebApplicationInitializer
如果我们在应用程序的其他地方使用 Spring,则可能已经有一个WebApplicationInitializer
用来加载 Spring 配置。如果我们使用以前的配置,将会得到一个错误。相反,我们应该使用现有的ApplicationContext
注册 Spring Security。例如,如果我们使用 Spring MVC,则SecurityWebApplicationInitializer
如下所示:
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
这只会为应用程序中的每个 URL 仅注册 springSecurityFilterChain 过滤器。之后,我们将确保WebSecurityConfig
已加载到我们现有的 ApplicationInitializer 中。例如,如果我们使用的是 Spring MVC,则将其添加到getRootConfigClasses()
public class MvcWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityConfig.class };
}
// ... other overrides ...
}
5.2 HttpSecurity
到目前为止,我们的WebSecurityConfig仅包含有关如何验证用户身份的信息。 Spring Security 如何知道我们要要求所有用户进行身份验证? Spring Security 如何知道我们要支持基于表单的身份验证?原因是WebSecurityConfigurerAdapter
在configure(HttpSecurity http)
方法中提供了默认配置,如下所示:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
上面的默认配置:
-
确保对我们应用程序的任何请求都需要对用户进行身份验证
-
允许用户使用基于表单的登录进行身份验证
-
允许用户使用 HTTP Basic 身份验证进行身份验证
您会注意到该配置与 XML 命名空间配置非常相似:
<http>
<intercept-url pattern="/**" access="authenticated"/>
<form-login />
<http-basic />
</http>
使用and()
方法表示等效于关闭 XML 标记的 Java 配置,该方法允许我们 continue 配置父级。如果您阅读该代码,这也很有意义。我要配置授权请求,并配置表单登录,并配置 HTTP 基本身份验证。
但是,Java 配置具有不同的默认 URL 和参数。创建自定义登录页面时,请记住这一点。结果是我们的 URL 更 RESTful。另外,使用 Spring Security 可以防止information leaks并不是很明显。例如:
5.3 Java 配置和表单登录
您可能想知道提示您登录时登录表单的来源,因为我们没有提及任何 HTML 文件或 JSP。由于 Spring Security 的默认配置没有显式设置登录页面的 URL,因此 Spring Security 将基于已启用的功能并使用处理提交的登录的 URL 的标准值(用户将使用的默认目标 URL)自动生成一个 URL。登录后发送至。
尽管自动生成的登录页面便于快速启动和运行,但是大多数应用程序都希望提供自己的登录页面。为此,我们可以如下所示更新配置:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login") (1)
.permitAll(); (2)
}
- (1) 更新后的配置指定登录页面的位置。
- (2) 我们必须授予所有用户(即未经身份验证的用户)访问我们登录页面的权限。
formLogin().permitAll()
方法允许向所有用户授予与基于表单的登录相关的所有 URL 的访问权限。
下面是我们当前配置中使用 JSP 实现的示例登录页面:
Note
下面的登录页面代表我们当前的配置。如果某些默认设置不能满足我们的需求,我们可以轻松地更新配置。
<c:url value="/login" var="loginUrl"/>
<form action="${loginUrl}" method="post"> (1)
<c:if test="${param.error != null}"> (2)
<p>
Invalid username and password.
</p>
</c:if>
<c:if test="${param.logout != null}"> (3)
<p>
You have been logged out.
</p>
</c:if>
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username"/> (4)
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password"/> (5)
</p>
<input type="hidden" (6)
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
<button type="submit" class="btn">Log in</button>
</form>
- (1) 到
/login
URL 的 POST 将尝试验证用户身份 - (2) 如果查询参数
error
存在,则尝试认证失败 - (3) 如果查询参数
logout
存在,则表明用户已成功注销 - (4) 用户名必须作为名为* username *的 HTTP 参数存在
- (5) 密码必须作为名为* password *的 HTTP 参数存在
- (6) 我们必须第 18.4.3 节“包括 CSRF 令牌”要了解更多信息,请阅读参考的第 18 章,跨站点请求伪造(CSRF)部分
5.4 授权请求
我们的示例仅要求对用户进行身份验证,并且对应用程序中的每个 URL 都进行了身份验证。我们可以通过将多个子级添加到http.authorizeRequests()
方法中来为 URL 指定自定义要求。例如:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() (1)
.antMatchers("/resources/**", "/signup", "/about").permitAll() (2)
.antMatchers("/admin/**").hasRole("ADMIN") (3)
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") (4)
.anyRequest().authenticated() (5)
.and()
// ...
.formLogin();
}
- (1)
http.authorizeRequests()
方法有多个子级,每个匹配器均按声明 Sequences 考虑。 - (2) 我们指定了任何用户都可以访问的多个 URL 模式。具体来说,如果 URL 以“/resources /”开头,等于“/signup”或等于“/about”,则任何用户都可以访问请求。
- (3) 任何以“/admin /”开头的 URL 都将限于角色为“ ROLE_ADMIN”的用户。您将注意到,由于我们正在调用
hasRole
方法,因此无需指定“ ROLE_”前缀。 - (4) 任何以“/db /”开头的 URL 都要求用户同时具有“ ROLE_ADMIN”和“ ROLE_DBA”。您会注意到,由于我们使用的是
hasRole
表达式,因此无需指定“ ROLE_”前缀。 - (5) 尚未匹配的任何 URL 仅要求对用户进行身份验证
5.5 处理注销
使用WebSecurityConfigurerAdapter
时,将自动应用注销功能。默认设置是访问 URL /logout
将通过以下方式注销用户:
-
使 HTTP 会话无效
-
清理配置的所有 RememberMe 身份验证
-
清除
SecurityContextHolder
-
重定向到
/login?logout
但是,与配置登录功能相似,您还可以使用各种选项来进一步自定义注销要求:
protected void configure(HttpSecurity http) throws Exception {
http
.logout() (1)
.logoutUrl("/my/logout") (2)
.logoutSuccessUrl("/my/index") (3)
.logoutSuccessHandler(logoutSuccessHandler) (4)
.invalidateHttpSession(true) (5)
.addLogoutHandler(logoutHandler) (6)
.deleteCookies(cookieNamesToClear) (7)
.and()
...
}
- (1) 提供注销支持。使用
WebSecurityConfigurerAdapter
时将自动应用。 - (2) 触发注销的 URL 发生(默认为
/logout
)。如果启用了 CSRF 保护(默认),则请求也必须是 POST。有关更多信息,请咨询JavaDoc。 - (3) 发生注销后重定向到的 URL。默认值为
/login?logout
。有关更多信息,请咨询JavaDoc。 - (4) 让我们指定一个自定义
LogoutSuccessHandler
。如果指定此选项,则logoutSuccessUrl()
将被忽略。有关更多信息,请咨询JavaDoc。 - (5) 指定注销时是否使
HttpSession
无效。默认情况下,这是“ true”。在幕后配置SecurityContextLogoutHandler
。有关更多信息,请咨询JavaDoc。 - (6) 添加
LogoutHandler
。默认情况下,将SecurityContextLogoutHandler
添加为最后的LogoutHandler
。 - (7) 允许指定成功注销后将删除的 cookie 名称。这是显式添加
CookieClearingLogoutHandler
的快捷方式。
Note
当然,也可以使用 XML 命名空间符号配置注销。请参阅 Spring Security XML 命名空间部分中logout element的文档以获取更多详细信息。
通常,为了自定义注销功能,您可以添加LogoutHandler
和/或LogoutSuccessHandler
实现。对于许多常见方案,使用流畅的 API 时会在后台应用这些处理程序。
5.5.1 LogoutHandler
通常,LogoutHandler
实现表示能够参与注销处理的类。期望它们被调用以执行必要的清理。因此,它们不应引发异常。提供了各种实现:
有关详情,请参见第 17.4 节“记住我的接口和实现”。
除了直接提供LogoutHandler
实现之外,fluent API 还提供了快捷方式,这些快捷方式在幕后提供了各自的LogoutHandler
实现。例如。 deleteCookies()
允许指定注销成功后要删除的一个或多个 cookie 的名称。与添加CookieClearingLogoutHandler
相比,这是捷径。
5.5.2 LogoutSuccessHandler
LogoutFilter
成功注销后调用LogoutSuccessHandler
,以处理例如重定向或转发到适当的目的地。请注意,该接口与LogoutHandler
几乎相同,但可能会引发异常。
提供以下实现:
-
HttpStatusReturningLogoutSuccessHandler
如上所述,您无需直接指定SimpleUrlLogoutSuccessHandler
。相反,Fluent 的 API 通过设置logoutSuccessUrl()
提供了快捷方式。这将在底下设置SimpleUrlLogoutSuccessHandler
。提供的 URL 将在注销后重定向到。默认值为/login?logout
。
HttpStatusReturningLogoutSuccessHandler
在 REST API 类型的场景中可能会很有趣。通过LogoutSuccessHandler
,您可以提供要返回的纯 HTTP 状态代码,而不是在成功注销后重定向到 URL。如果未配置,默认情况下将返回状态码 200.
5.5.3 其他与注销有关的参考
-
CSRF 警告中的Logging Out
-
第Single Logout节(CAS 协议)
-
Spring Security XML 命名空间部分中的logout element的文档
5.6 Authentication
到目前为止,我们只看了最基本的身份验证配置。让我们看一下配置身份验证的一些高级选项。
5.6.1 内存中身份验证
我们已经看到了为单个用户配置内存中身份验证的示例。下面是配置多个用户的示例:
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build());
manager.createUser(User.withUsername("admin").password("password").roles("USER","ADMIN").build());
return manager;
}
5.6.2 JDBC 身份验证
您可以找到更新以支持基于 JDBC 的身份验证。下面的示例假定您已经在应用程序中定义了DataSource
。 jdbc-javaconfig示例提供了使用基于 JDBC 的身份验证的完整示例。
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withDefaultSchema()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
5.6.3 LDAP 认证
您可以找到更新以支持基于 LDAP 的身份验证。 ldap-javaconfig示例提供了使用基于 LDAP 的身份验证的完整示例。
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups");
}
上面的示例使用以下 LDIF 和嵌入式 Apache DS LDAP 实例。
users.ldif.
dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people
dn: uid=admin,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rod Johnson
sn: Johnson
uid: admin
userPassword: password
dn: uid=user,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Dianne Emu
sn: Emu
uid: user
userPassword: password
dn: cn=user,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: user
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
uniqueMember: uid=user,ou=people,dc=springframework,dc=org
dn: cn=admin,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: admin
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
5.6.4 AuthenticationProvider
您可以通过将自定义AuthenticationProvider
公开为 bean 来定义自定义身份验证。例如,以下假设SpringAuthenticationProvider
实现AuthenticationProvider
,将自定义身份验证:
Note
仅在未填充AuthenticationManagerBuilder
时使用
@Bean
public SpringAuthenticationProvider springAuthenticationProvider() {
return new SpringAuthenticationProvider();
}
5.6.5 UserDetailsService
您可以通过将自定义UserDetailsService
公开为 bean 来定义自定义身份验证。例如,以下假设SpringDataUserDetailsService
实现UserDetailsService
,将自定义身份验证:
Note
仅当尚未填充AuthenticationManagerBuilder
且未定义AuthenticationProviderBean
时才使用此选项。
@Bean
public SpringDataUserDetailsService springDataUserDetailsService() {
return new SpringDataUserDetailsService();
}
您还可以通过将PasswordEncoder
公开为 bean 来定制密码的 encodings。例如,如果使用 bcrypt,则可以添加如下所示的 bean 定义:
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
5.6.6 LDAP 验证
5.7 多个 HttpSecurity
我们可以配置多个 HttpSecurity 实例,就像我们可以拥有多个<http>
块一样。关键是要多次扩展WebSecurityConfigurerAdapter
。例如,以下是对以/api/
开头的 URL 具有不同配置的示例。
@EnableWebSecurity
public class MultiHttpSecurityConfig {
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build());
manager.createUser(User.withUsername("admin").password("password").roles("USER","ADMIN").build());
return manager;
}
@Configuration
@Order(1) (1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**") (2)
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
@Configuration (3)
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
- 正常配置身份验证
- (1) 创建一个包含
@Order
的WebSecurityConfigurerAdapter
实例,以指定应首先考虑哪个WebSecurityConfigurerAdapter
。 - (2)
http.antMatcher
声明此HttpSecurity
仅适用于以/api/
开头的 URL - (3) 创建
WebSecurityConfigurerAdapter
的另一个实例。如果网址不是以/api/
开头,则将使用此配置。在ApiWebSecurityConfigurationAdapter
之后考虑此配置,因为它在1
之后具有@Order
值(没有@Order
默认为最后)。
5.8 方法安全性
从 2.0 版开始,Spring Security 大大改善了对为服务层方法增加安全性的支持。它提供对 JSR-250Comments 安全性以及框架原始@Secured
Comments 的支持。从 3.0 开始,您还可以使用新的expression-based annotations。您可以使用intercept-methods
元素修饰 bean 声明,从而对单个 bean 应用安全性,或者可以使用 AspectJ 样式切入点在整个服务层中保护多个 bean。
5.8.1 EnableGlobalMethodSecurity
我们可以在任何@Configuration
实例上使用@EnableGlobalMethodSecurity
Comments 启用基于 Comments 的安全性。例如,以下将启用 Spring Security 的@Secured
Comments。
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
向方法(在类或接口上)添加 Comments 将相应地限制对该方法的访问。 Spring Security 的本机 Comments 支持为该方法定义了一组属性。这些将被传递给 AccessDecisionManager 使其做出实际决定:
public interface BankService {
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account readAccount(Long id);
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account[] findAccounts();
@Secured("ROLE_TELLER")
public Account post(Account account, double amount);
}
可以使用以下命令启用对 JSR-250 注解的支持
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class MethodSecurityConfig {
// ...
}
这些是基于标准的,并允许应用基于角色的简单约束,但是没有 Spring Security 的本机 Comments 的强大功能。要使用新的基于表达式的语法,您可以使用
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
// ...
}
而等效的 Java 代码将是
public interface BankService {
@PreAuthorize("isAnonymous()")
public Account readAccount(Long id);
@PreAuthorize("isAnonymous()")
public Account[] findAccounts();
@PreAuthorize("hasAuthority('ROLE_TELLER')")
public Account post(Account account, double amount);
}
5.8.2 GlobalMethodSecurityConfiguration
有时,您可能需要执行比@EnableGlobalMethodSecurity
Comments 允许所允许的操作更为复杂的操作。对于这些实例,您可以扩展GlobalMethodSecurityConfiguration
,以确保@EnableGlobalMethodSecurity
Comments 出现在子类中。例如,如果要提供自定义MethodSecurityExpressionHandler
,则可以使用以下配置:
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
// ... create and return custom MethodSecurityExpressionHandler ...
return expressionHandler;
}
}
有关可以覆盖的方法的其他信息,请参阅GlobalMethodSecurityConfiguration
Javadoc。
5.9 后处理已配置的对象
Spring Security 的 Java 配置并未公开其配置的每个对象的每个属性。这简化了大多数用户的配置。毕竟,如果每个属性都公开,则用户可以使用标准 Bean 配置。
尽管有充分的理由不直接公开每个属性,但用户可能仍需要更多高级配置选项。为了解决这个问题,Spring Security 引入了ObjectPostProcessor
的概念,该概念可用于修改或替换 Java 配置创建的许多 Object 实例。例如,如果要在FilterSecurityInterceptor
上配置filterSecurityPublishAuthorizationSuccess
属性,则可以使用以下命令:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
public <O extends FilterSecurityInterceptor> O postProcess(
O fsi) {
fsi.setPublishAuthorizationSuccess(true);
return fsi;
}
});
}
5.10 自定义 DSL
您可以在 Spring Security 中提供自己的自定义 DSL。例如,您可能会有类似以下内容的内容:
public class MyCustomDsl extends AbstractHttpConfigurer<CorsConfigurerMyCustomDsl, HttpSecurity> {
private boolean flag;
@Override
public void init(H http) throws Exception {
// any method that adds another configurer
// must be done in the init method
http.csrf().disable();
}
@Override
public void configure(H http) throws Exception {
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
// here we lookup from the ApplicationContext. You can also just create a new instance.
MyFilter myFilter = context.getBean(MyFilter.class);
myFilter.setFlag(flag);
http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
}
public MyCustomDsl flag(boolean value) {
this.flag = value;
return this;
}
public static MyCustomDsl customDsl() {
return new MyCustomDsl();
}
}
Note
实际上就是实现HttpSecurity.authorizeRequests()
之类的方法的方式。
然后可以像下面这样使用自定义 DSL:
@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.apply(customDsl())
.flag(true)
.and()
...;
}
}
该代码按以下 Sequences 调用:
-
调用``的 configure 方法中的代码
-
MyCustomDsl 的 init 方法中的代码被调用
-
MyCustomDsl 的 configure 方法中的代码被调用
如果需要,可以使用SpringFactories
默认情况下WebSecurityConfiguerAdapter
添加MyCustomDsl
。例如,您将在名为META-INF/spring.factories
的 Classpath 上创建具有以下内容的资源:
META-INF/spring.factories.
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl
希望禁用默认设置的用户可以明确地这样做。
@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.apply(customDsl()).disable()
...;
}
}