暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring Security

产教Code 2019-09-16
240

概述

介绍

WebSecurityConfigurerAdapter是Spring Security Config内置提供的一个WebSecurityConfigurer抽象实现类。WebSecurityConfigurerAdapter存在的目的是提供一个方便开发人员配置WebSecurity的基类。它提供了一组全方位配置WebSecurity的缺省方法实现。开发人员只要继承WebSecurityConfigurerAdapter提供自己的实现类,哪怕不覆盖WebSecurityConfigurerAdapter的任何一个方法,都得到了一个配置WebSecurity的安全配置器WebSecurityConfigurer实例。但通常情况下,开发人员都有自己特定的安全配置和要求,这时候就可以在自己提供的WebSecurityConfigurerAdapter子实现类中提供自己的方法覆盖WebSecurityConfigurerAdapter相应的方法从而对WebSecurity实施定制。


WebSecurityConfigurerAdapter为开发人员提供了如下功能 :

1.构建一个用于配置WebSecurity的WebSecurityConfigurerAdapter对象,可以指定使用或者不使用缺省配置,默认构造函数使用缺省配置;

2.提供可覆盖实现的方法void configure(AuthenticationManagerBuilder auth) ,允许开发人员配置目标WebSecurity所使用的AuthenticationManager的双亲AuthenticationManager;该方法缺省实现的效果是该双亲AuthenticationManager来自AuthenticationConfiguration定义的AuthenticationManager(其实是来自IoC容器的类型为AuthenticationManager的一个bean);

通过覆盖实现该方法,开发人员可以定制认证机制,比如设置成基于内存的认证,基于数据库的认证,基于LDAP的认证,甚至这些认证机制的一个组合,设置AuthenticationManager的双亲关系,所使用的PasswordEncoder等等;

3. 提供可覆盖实现的空方法void configure(WebSecurity web),允许开发人员覆盖实现配置WebSecurity,比如设置哪些URL要忽略安全等等;

通过覆盖实现该方法,开发人员可以定制WebSecurity,主要是除了HttpSecurity之外的安全控制,比如忽略某些静态公开资源或者动态公开资源的安全 ,设置需要使用的防火墙实例,设置权限评估器,安全表达式处理器等;

4.WebSecurityConfigurerAdapter自身是一个WebSecurityConfigurer,它在自己的初始化方法init()中创建了HttpSecurity http安全构建器对象,并在缺省情况下(disableDefaults为false)应用了如下HttpSecurity初始配置:

   

 http
.csrf().and() // 应用 CsrfConfigurer
.addFilter(new WebAsyncManagerIntegrationFilter()) // 添加过滤器 WebAsyncManagerIntegrationFilter
.exceptionHandling().and() // 应用 ExceptionHandlingConfigurer
.headers().and() // 应用 HeadersConfigurer
.sessionManagement().and() // 应用 SessionManagementConfigurer
.securityContext().and() // 应用 SecurityContextConfigurer
.requestCache().and() // 应用 RequestCacheConfigurer
.anonymous().and() // 应用 AnonymousConfigurer
.servletApi().and() // 应用 ServletApiConfigurer
.apply(new DefaultLoginPageConfigurer<>()).and() // 应用 DefaultLoginPageConfigurer
.logout(); // 应用 LogoutConfigurer




// 使用 SpringFactoriesLoader 加载 classpath 上所有jar包中各自的 META-INF/spring.factories 属性文件
// 中指定的 AbstractHttpConfigurer,应用到 http
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);




for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}



5.提供可覆盖实现的空方法void configure(HttpSecurity http),允许开发人员配置目标HttpSecurity;这里该方法缺省的实现对HttpSecurity的安全配置如下:

  •  对任何请求要求用户已认证(通俗地讲,用户必须先登录才能访问任何资源);

  •  启用用户名密码表单登录认证机制;

  • 启用Http Basic认证机制;

通过覆盖实现该方法,开发人员可以定制HttpSecurity;

http
.authorizeRequests().anyRequest().authenticated().and()
// 上面行应用一个 ExpressionUrlAuthorizationConfigurer,要求所有URL必须登录认证后才能访问
.formLogin().and() // 应用 FormLoginConfigurer
.httpBasic(); // 应用 HttpBasicConfigurer


   

WebSecurityConfigurerAdapter

WebSecurityConfigurerAdapter提供了简洁方式来创建WebSecurityConfigurer,其作为基类,可通过实现该类自定义配置类。其自动从SpringFactoriesLoader查找AbstractHttpConfigurer让我们去扩展,想要实现必须创建一个AbstractHttpConfigurer的扩展类

其源码分析:

//1.init初始化:获取HttpSecurity和配置FilterSecurityInterceptor拦截器到WebSecurity
public void init(final WebSecurity web) throws Exception {
//获取HttpSecurity
final HttpSecurity http = getHttp();
//配置FilterSecurityInterceptor拦截器到WebSecurity
web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
public void run() {
FilterSecurityInterceptor securityInterceptor = http
.getSharedObject(FilterSecurityInterceptor.class);
web.securityInterceptor(securityInterceptor);
}
});
}
......
//2.获取HttpSecurity的过程
protected final HttpSecurity getHttp() throws Exception {
if (http != null) {
return http;
}




DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
.postProcess(new DefaultAuthenticationEventPublisher());
localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);




AuthenticationManager authenticationManager = authenticationManager();
authenticationBuilder.parentAuthenticationManager(authenticationManager);
Map<Class<? extends Object>, Object> sharedObjects = createSharedObjects();




http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
sharedObjects);
if (!disableDefaults) {
// 默认的HttpSecurity的配置
http
//添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用,禁用csrf().disable()
.csrf().and()
//添加WebAsyncManagerIntegrationFilter
.addFilter(new WebAsyncManagerIntegrationFilter())
//允许配置异常处理
.exceptionHandling().and()
//将安全标头添加到响应
.headers().and()
//允许配置会话管理
.sessionManagement().and()
//HttpServletRequest之间的SecurityContextHolder创建securityContext管理
.securityContext().and()
//允许配置请求缓存
.requestCache().and()
//允许配置匿名用户
.anonymous().and()
//HttpServletRequestd的方法和属性注册在SecurityContext中
.servletApi().and()
//使用默认登录页面
.apply(new DefaultLoginPageConfigurer<>()).and()
//提供注销支持
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);




for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
configure(http);
return http;
}...//3.可重写方法实现自定义的HttpSecurityprotected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");




http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();}....

从源码init初始化模块中的“获取HttpSecurity”和“配置FilterSecurityInterceptor拦截器到WebSecurity”中可以看出,想要spring Security如何知道我们要求所有用户都经过身份验证?Spring Security如何知道我们想要支持基于表单的身份验证?只要重写protected void configure(HttpSecurity http) throws Exception方法即可。因此我们需要理解HttpSecurity的方法的作用

HttpSecurity

HttpSecurity基于Web的安全性允许为特定的http请求进行配置。其有很多方法,列举一些常用的如下表:


HttpSecurity还有很多方法供我们使用,去配置HttpSecurity。

由于太多这边就不一一说明,有兴趣可去研究。

文章转载自产教Code,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论