深圳幻海软件技术有限公司 欢迎您!

Spring Security的配置机制早就变了,你发现了吗?

2023-02-28

以前胖哥说过SecurityConfigurerAdapter会在即将发布的5.7版本作废,从SpringSecurity5.4版本开始会提供一个原型范围的HttpSecurity来帮助我们构建过滤器链SecurityFilterChain:复制@Bean(HTTPSECURITY_BEAN_NAM

以前胖哥说过SecurityConfigurerAdapter会在即将发布的5.7版本作废,从Spring Security 5.4版本开始会提供一个原型范围的HttpSecurity来帮助我们构建过滤器链SecurityFilterChain:

 @Bean(HTTPSECURITY_BEAN_NAME)
 @Scope("prototype")
 HttpSecurity httpSecurity() throws Exception {
  WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
    this.context);
  AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
    this.objectPostProcessor, passwordEncoder);
  authenticationBuilder.parentAuthenticationManager(authenticationManager());
  HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
  // @formatter:off
  http
   .csrf(withDefaults())
   .addFilter(new WebAsyncManagerIntegrationFilter())
   .exceptionHandling(withDefaults())
   .headers(withDefaults())
   .sessionManagement(withDefaults())
   .securityContext(withDefaults())
   .requestCache(withDefaults())
   .anonymous(withDefaults())
   .servletApi(withDefaults())
   .apply(new DefaultLoginPageConfigurer<>());
  http.logout(withDefaults());
  // @formatter:on
  return http;
 }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

这里会构建基于原型的HttpSecurityBean,并且初始化了一些默认配置供我们来使用。涉及Spring Security的日常开发都是围绕这个类进行的,所以这个类是学习Spring Security的重中之重。

基于原型(prototype)的Spring Bean的一个典型应用场景。

基本配置

日常我们使用的一些配置项如下:


方法  说明
requestMatchers() 为SecurityFilterChain提供URL拦截策略,具体还提供了antMatcher和mvcMathcer
openidLogin() 用于基于 OpenId 的验证
headers() 将安全标头添加到响应,比如说简单的 XSS 保护
cors()  配置跨域资源共享( CORS )
sessionManagement() 配置会话管理
portMapper()  配置一个PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的对象使用 PortMapper 从 HTTP 重定向到 HTTPS 或者从 HTTPS 重定向到 HTTP。默认情况下,Spring Security使用一个PortMapperImpl映射 HTTP 端口8080到 HTTPS 端口8443,HTTP 端口80到 HTTPS 端口443
jee() 配置基于容器的预认证。在这种情况下,认证由Servlet容器管理
x509()  配置基于x509的预认证
rememberMe  配置“记住我”的验证
authorizeRequests() 基于使用HttpServletRequest限制访问
requestCache()  配置请求缓存
exceptionHandling() 配置错误处理
securityContext() 在HttpServletRequests之间的SecurityContextHolder上设置SecurityContext的管理。当使用WebSecurityConfigurerAdapter时,这将自动应用
servletApi()  将HttpServletRequest方法与在其上找到的值集成到SecurityContext中。当使用WebSecurityConfigurerAdapter时,这将自动应用
csrf()  添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用
logout()  添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到/login?success
anonymous() 配置匿名用户的表示方法。当与WebSecurityConfigurerAdapter结合使用时,这将自动应用。默认情况下,匿名用户将使用org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 ROLE_ANONYMOUS
authenticationManager() 配置AuthenticationManager
authenticationProvider()  添加AuthenticationProvider
formLogin() 指定支持基于表单的身份验证。如果未指定FormLoginConfigurer#loginPage(String),则将生成默认登录页面
oauth2Login() 根据外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份验证
oauth2Client()  OAuth2.0 客户端相关的配置
oauth2ResourceServer()  OAuth2.0资源服务器相关的配置
requiresChannel() 配置通道安全。为了使该配置有用,必须提供至少一个到所需信道的映射
httpBasic() 配置 Http Basic 验证
addFilter() 添加一个已经在内置过滤器注册表注册过的过滤器实例或者子类
addFilterBefore() 在指定的Filter类之前添加过滤器
addFilterAt() 在指定的Filter类的位置添加过滤器
addFilterAfter()  在指定的Filter类的之后添加过滤器
and() 连接以上策略的连接器,用来组合安全策略。实际上就是”而且”的意思
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

高级玩法

新手建议先把上面的基本玩法有选择的弄明白,然后有精力的话去研究下HttpSecurity的高级玩法。

apply

这个方法用来把其它的一些配置合并到当前的配置中去,形成插件化,支持SecurityConfigurerAdapter或者SecurityConfigurer的实现。其实内置的一些配置都是以这种形式集成到HttpSecurity中去的。例如文章开头的配置中有默认登录页面相关的配置:

 httpSecurity.apply(new DefaultLoginPageConfigurer<>());
  • 1.

胖哥就利用这个搞了一个支持小程序登录和验证码登录的扩展 spring-security-login-extension。

objectPostProcessor配置一个自定义ObjectPostProcessor。ObjectPostProcessor可以改变某些配置内部的机制,这些配置往往不直接对外提供操作接口。

获取、移除配置类

getConfigurer用来获取已经apply的配置类;getConfigurers用来获取已经apply某个类型的所有配置类。这个现在是我最喜欢的自定义的方式。

配置、获取SharedObjectShared

Object是在配置中进行共享的一些对象,HttpSecurity共享了一些非常有用的对象可以供各个配置之间共享,比如AuthenticationManager。相关的方法有setSharedObject、getSharedObject、getSharedObjects。

获取SecurityFilterChainHttpSecurity也提供了构建目标对象SecurityFilterChain的实例的方法。你可以通过build()来对配置进行初次构建;也可以通过getObject()来获取已经构建的实例;甚至你可以使用getOrBuild()来进行直接获取实例或者构建实例。

所以新的配置都是这样的:


@Bean
SecurityFilterChain securityFilterChain (HttpSecurity http) {
    http.cors();
    return http.build();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

记住每一个HttpSecurity只能被构建成功一次。

这一篇非常重要本篇东西非常重要,不是马上就能掌握的,需要有些耐心,需要在使用和学习中总结和发现。