我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么理解SecurityConfigurer

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么理解SecurityConfigurer

这篇文章主要讲解了“怎么理解SecurityConfigurer”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解SecurityConfigurer”吧!

1. SecurityConfigurerSecurityConfigurer

本身是一个接口,我们来看下:

public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {   void init(B builder) throws Exception;   void configure(B builder) throws Exception; }

可以看到,SecurityConfigurer 中主要是两个方法,init 和 configure。

init 就是一个初始化方法。而 configure 则是一个配置方法。这里只是规范了方法的定义,具体的实现则在不同的实现类中。

需要注意的是这两个方法的参数类型都是一个泛型 B,也就是 SecurityBuilder 的子类,关于 SecurityBuilder  ,它是用来构建过滤器链的,松哥将在下篇文章中和大家介绍。

SecurityConfigurer 有三个实现类:

  • SecurityConfigurerAdapter

  • GlobalAuthenticationConfigurerAdapter

  • WebSecurityConfigurer

我们分别来看。

1.1 SecurityConfigurerAdapter

SecurityConfigurerAdapter实现了 SecurityConfigurer  接口,我们所使用的大部分的 xxxConfigurer 也都是 SecurityConfigurerAdapter 的子类。

SecurityConfigurerAdapter 在 SecurityConfigurer  的基础上,还扩展出来了几个非常好用的方法,我们一起来看下:

public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>   implements SecurityConfigurer<O, B> {  private B securityBuilder;   private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor();   public void init(B builder) throws Exception {  }   public void configure(B builder) throws Exception {  }   public B and() {   return getBuilder();  }  protected final B getBuilder() {   if (securityBuilder == null) {    throw new IllegalStateException("securityBuilder cannot be null");   }   return securityBuilder;  }  @SuppressWarnings("unchecked")  protected <T> T postProcess(T object) {   return (T) this.objectPostProcessor.postProcess(object);  }  public void addObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {   this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);  }  public void setBuilder(B builder) {   this.securityBuilder = builder;  }  private static final class CompositeObjectPostProcessor implements    ObjectPostProcessor<Object> {   private List<ObjectPostProcessor<?>> postProcessors = new ArrayList<>();    @SuppressWarnings({ "rawtypes", "unchecked" })   public Object postProcess(Object object) {    for (ObjectPostProcessor opp : postProcessors) {     Class<?> oppClass = opp.getClass();     Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,       ObjectPostProcessor.class);     if (oppType == null || oppType.isAssignableFrom(object.getClass())) {      object = opp.postProcess(object);     }    }    return object;   }   private boolean addObjectPostProcessor(     ObjectPostProcessor<?> objectPostProcessor) {    boolean result = this.postProcessors.add(objectPostProcessor);    postProcessors.sort(AnnotationAwareOrderComparator.INSTANCE);    return result;   }  } }
  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. CompositeObjectPostProcessor 首先一开始声明了一个 CompositeObjectPostProcessor  实例,CompositeObjectPostProcessor 是 ObjectPostProcessor 的一个实现,ObjectPostProcessor  本身是一个后置处理器,该后置处理器默认有两个实现,AutowireBeanFactoryObjectPostProcessor 和  CompositeObjectPostProcessor。其中 AutowireBeanFactoryObjectPostProcessor 主要是利用了  AutowireCapableBeanFactory 对 Bean 进行手动注册,因为在 Spring Security 中,很多对象都是手动 new  出来的,这些 new 出来的对象和容器没有任何关系,利用 AutowireCapableBeanFactory 可以将这些手动 new  出来的对象注入到容器中,而 AutowireBeanFactoryObjectPostProcessor  的主要作用就是完成这件事;CompositeObjectPostProcessor 则是一个复合的对象处理器,里边维护了一个 List 集合,这个 List  集合中,大部分情况下只存储一条数据,那就是  AutowireBeanFactoryObjectPostProcessor,用来完成对象注入到容器的操作,如果用户自己手动调用了  addObjectPostProcessor 方法,那么 CompositeObjectPostProcessor 集合中维护的数据就会多出来一条,在  CompositeObjectPostProcessor#postProcess 方法中,会遍历集合中的所有 ObjectPostProcessor,挨个调用其  postProcess 方法对对象进行后置处理。

  3. and 方法,该方法返回值是一个 securityBuilder,securityBuilder  实际上就是 HttpSecurity,我们在 HttpSecurity 中去配置不同的过滤器时,可以使用 and 方法进行链式配置,就是因为这里定义了 and  方法并返回了 securityBuilder 实例。

这便是 SecurityConfigurerAdapter 的主要功能,后面大部分的  xxxConfigurer 都是基于此类来实现的。

1.2  GlobalAuthenticationConfigurerAdapter

GlobalAuthenticationConfigurerAdapter  看名字就知道是一个跟全局配置有关的东西,它本身实现了 SecurityConfigurerAdapter  接口,但是并未对方法做具体的实现,只是将泛型具体化了:

@Order(100) public abstract class GlobalAuthenticationConfigurerAdapter implements   SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> {   public void init(AuthenticationManagerBuilder auth) throws Exception {  }   public void configure(AuthenticationManagerBuilder auth) throws Exception {  } }

可以看到,SecurityConfigurer 中的泛型,现在明确成了 AuthenticationManager 和  AuthenticationManagerBuilder。所以 GlobalAuthenticationConfigurerAdapter  的实现类将来主要是和配置 AuthenticationManager 有关。当然也包括默认的用户名密码也是由它的实现类来进行配置的。

我们在  Spring Security 中使用的 AuthenticationManager  其实可以分为两种,一种是局部的,另一种是全局的,这里主要是全局的配置。

1.3 WebSecurityConfigurer

还有一个实现类就是  WebSecurityConfigurer,这个可能有的小伙伴比较陌生,其实他就是我们天天用的 WebSecurityConfigurerAdapter  的父接口。

所以 WebSecurityConfigurer 的作用就很明确了,用户扩展用户自定义的配置。

SecurityConfigurer 默认主要是这三个实现,考虑到大多数的过滤器配置都是通过 SecurityConfigurerAdapter  进行扩展的,因此我们今天就通过这条线进行展开。另外两条线松哥也将撸两篇文章和大家介绍。

2.  SecurityConfigurerAdapter

SecurityConfigurerAdapter 的实现主要也是三大类:

  • UserDetailsAwareConfigurer

  • AbstractHttpConfigurer

  • LdapAuthenticationProviderConfigurer

考虑到 LDAP  现在使用很少,所以这里我来和大家重点介绍下前两个。

2.1  UserDetailsAwareConfigurer

这个配置类看名字大概就知道这是用来配置用户类的。

怎么理解SecurityConfigurer

AbstractDaoAuthenticationConfigurer

AbstractDaoAuthenticationConfigurer  中所做的事情比较简单,主要是构造了一个默认的 DaoAuthenticationProvider,并为其配置 PasswordEncoder 和  UserDetailsService。

UserDetailsServiceConfigurer

UserDetailsServiceConfigurer 重写了 AbstractDaoAuthenticationConfigurer 中的  configure 方法,在 configure 方法执行之前加入了 initUserDetailsService 方法,以方便开发展按照自己的方式去初始化  UserDetailsService。不过这里的 initUserDetailsService 方法是空方法。

UserDetailsManagerConfigurer

UserDetailsManagerConfigurer 中实现了  UserDetailsServiceConfigurer 中定义的 initUserDetailsService 方法,具体的实现逻辑就是将  UserDetailsBuilder 所构建出来的 UserDetails 以及提前准备好的 UserDetails 中的用户存储到  UserDetailsService 中。

该类同时添加了 withUser 方法用来添加用户,同时还增加了一个  UserDetailsBuilder 用来构建用户,这些逻辑都比较简单,小伙伴们可以自行查看。

JdbcUserDetailsManagerConfigurer

JdbcUserDetailsManagerConfigurer  在父类的基础上补充了 DataSource 对象,同时还提供了相应的数据库查询方法。

InMemoryUserDetailsManagerConfigurer

InMemoryUserDetailsManagerConfigurer 在父类的基础上重写了构造方法,将父类中的 UserDetailsService  实例定义为 InMemoryUserDetailsManager。

DaoAuthenticationConfigurer

DaoAuthenticationConfigurer 继承自  AbstractDaoAuthenticationConfigurer,只是在构造方法中修改了一下 userDetailsService 而已。

有小伙伴可能要问了,JdbcUserDetailsManagerConfigurer 或者  InMemoryUserDetailsManagerConfigurer,到底在哪里可以用到呀?

松哥给大家举一个简单的例子:

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {      @Override     protected void configure(AuthenticationManagerBuilder auth) throws Exception {         auth.inMemoryAuthentication().withUser("javaboy")                 .password("{noop}123")                 .roles("admin");     }      @Override     protected void configure(HttpSecurity http) throws Exception {         http.authorizeRequests()                 .anyRequest().authenticated()                 //省略     } }

当你调用 auth.inMemoryAuthentication 进行配置时,实际上调用的就是  InMemoryUserDetailsManagerConfigurer。

这下明白了吧!

2.2  AbstractHttpConfigurer

AbstractHttpConfigurer  这一派中的东西非常多,我们所有的过滤器配置,都是它的子类,我们来看下都有哪些类?

怎么理解SecurityConfigurer

可以看到,它的实现类还是非常多的。

这么多实现类,松哥就不一一给大家介绍了,我挑一个常用的 FormLoginConfigurer  来给大家详细介绍,只要大家把这个理解了,其他的照猫画虎就很好理解了。

我们一个一个来看。

2.2.1  AbstractHttpConfigurer

AbstractHttpConfigurer 继承自  SecurityConfigurerAdapter,并增加了两个方法,disable 和 withObjectPostProcessor:

public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>   extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {     @SuppressWarnings("unchecked")  public B disable() {   getBuilder().removeConfigurer(getClass());   return getBuilder();  }   @SuppressWarnings("unchecked")  public T withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {   addObjectPostProcessor(objectPostProcessor);   return (T) this;  } }

这两个方法松哥之前都有给大家介绍过,disable 基本上是大家的老熟人了,我们常用的 .csrf().disable()  就是出自这里,那么从这里我们也可以看到 disable 的实现原理,就是从 getBuilder 中移除相关的 xxxConfigurer,getBuilder  方法获取到的实际上就是 HttpSecurity,所以移除掉 xxxConfigurer 实际上就是从过滤器链中移除掉某一个过滤器,例如  .csrf().disable() 就是移除掉处理 csrf 的过滤器。

另一个增加的方法是  withObjectPostProcessor,这是为配置类添加手动添加后置处理器的。在 AbstractHttpConfigurer  的父类中其实有一个类似的方法就是 addObjectPostProcessor,但是 addObjectPostProcessor 只是一个添加方法,返回值为  void,而 withObjectPostProcessor 的返回值是当前配置类,也就是 xxxConfigurer,所以如果使用  withObjectPostProcessor 的话,可以使用链式配置,事实上,在松哥之前的文章,以及  vhr(https://github.com/lenve/vhr) 项目中,使用的也都是 withObjectPostProcessor  方法(当然,你也可以使用 addObjectPostProcessor,最终效果是一样的)。

2.2.2  AbstractAuthenticationFilter

ConfigurerAbstractAuthenticationFilterConfigurer  类的功能比较多,源码也是相当相当长。不过我们只需要抓住两点即可,init 方法和 configure 方法,因为这两个方法是所有 xxxConfigurer  的灵魂。

@Override public void init(B http) throws Exception {  updateAuthenticationDefaults();  updateAccessDefaults(http);  registerDefaultAuthenticationEntryPoint(http); }

init 方法主要干了三件事:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. updateAuthenticationDefaults 主要是配置了登录处理地址,失败跳转地址,注销成功跳转地址。

  3. updateAccessDefaults 方法主要是对 loginPage、loginProcessingUrl、failureUrl 进行  permitAll 设置(如果用户配置了 permitAll 的话)。

  4. registerDefaultAuthenticationEntryPoint 则是注册异常的处理器。

再来看 configure  方法:

@Override public void configure(B http) throws Exception {  PortMapper portMapper = http.getSharedObject(PortMapper.class);  if (portMapper != null) {   authenticationEntryPoint.setPortMapper(portMapper);  }  RequestCache requestCache = http.getSharedObject(RequestCache.class);  if (requestCache != null) {   this.defaultSuccessHandler.setRequestCache(requestCache);  }  authFilter.setAuthenticationManager(http    .getSharedObject(AuthenticationManager.class));  authFilter.setAuthenticationSuccessHandler(successHandler);  authFilter.setAuthenticationFailureHandler(failureHandler);  if (authenticationDetailsSource != null) {   authFilter.setAuthenticationDetailsSource(authenticationDetailsSource);  }  SessionAuthenticationStrategy sessionAuthenticationStrategy = http    .getSharedObject(SessionAuthenticationStrategy.class);  if (sessionAuthenticationStrategy != null) {   authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);  }  RememberMeServices rememberMeServices = http    .getSharedObject(RememberMeServices.class);  if (rememberMeServices != null) {   authFilter.setRememberMeServices(rememberMeServices);  }  F filter = postProcess(authFilter);  http.addFilter(filter); }

configure  中的逻辑就很简答了,构建各种各样的回调函数设置给 authFilter,authFilter 再去 postProcess 中走一圈注册到 Spring  容器中,最后再把 authFilter 添加到过滤器链中。

这便是 AbstractAuthenticationFilterConfigurer  的主要功能。需要提醒大家的是,我们日常配置的,如:

  • loginPage

  • loginProcessingUrl

  • permitAll

  • defaultSuccessUrl

  • failureUrl

  • ...

等方法都是在这里定义的。

最后我们再来看看 FormLoginConfigurer。

2.2.3  FormLoginConfigurer

FormLoginConfigurer 在定义是,明确了  AbstractAuthenticationFilterConfigurer 中的泛型是  UsernamePasswordAuthenticationFilter,也就是我们这里最终要配置的过滤是  UsernamePasswordAuthenticationFilter。

FormLoginConfigurer 重写了 init  方法,配置了一下默认的登录页面。其他的基本上都是从父类来的,未做太多改变。

另外我们日常配置的很多东西也是来自这里:

怎么理解SecurityConfigurer

感谢各位的阅读,以上就是“怎么理解SecurityConfigurer”的内容了,经过本文的学习后,相信大家对怎么理解SecurityConfigurer这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么理解SecurityConfigurer

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

CAP定理怎么理解

本篇内容主要讲解“CAP定理怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“CAP定理怎么理解”吧!计算机界有很多高大上又难于理解的术语,CAP就是其中之一, 什么一致性(Consiste
2023-06-05
2024-04-02

javascript怎么理解

这篇文章将为大家详细讲解有关javascript怎么理解,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,给用户提供更好的体验。2.可
2023-06-14

怎么理解ReentrantLock

这篇文章主要介绍“怎么理解ReentrantLock”,在日常操作中,相信很多人在怎么理解ReentrantLock问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解ReentrantLock”的疑惑有所
2023-06-16

怎么理解InitialContext

InitialContext是Java中的一个类,它提供了与命名和目录服务进行交互的接口。通过InitialContext,可以获取到命名和目录服务中的对象和资源。理解InitialContext可以从以下几个方面进行考虑:1. 定义:In
2023-09-08

怎么理解SVM

这篇文章主要介绍“怎么理解SVM”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么理解SVM”文章能帮助大家解决问题。SVM分类两个点。已知两个样本点,如果用SVM模型,决策边界就是线g,它的斜率为
2023-06-19

怎么理解dubbo

这篇文章将为大家详细讲解有关怎么理解dubbo,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. Dubbo是什么?Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调
2023-06-05

怎么理解shell

怎么理解shell,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行
2023-06-04

Orleans怎么理解

Orleans怎么理解,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、介绍Orleans是一个框架,提供了一个直接的方法来构建分布式高规模计算应用程序默认可扩展 -》 O
2023-06-19

怎么理解JavaScript

这篇文章主要讲解了“怎么理解JavaScript”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解JavaScript”吧!1、JavaScript是运行在浏览器上的 脚本语言,简称JS
2023-06-25

怎么理解HashMap

这篇文章主要讲解了“怎么理解HashMap”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解HashMap”吧!1、HashMap添加一个键值对的过程是怎么样的?这是网上找的一张流程图,
2023-06-16

Hibernate Session管理怎么理解

这篇文章主要介绍“Hibernate Session管理怎么理解”,在日常操作中,相信很多人在Hibernate Session管理怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Hibernate S
2023-06-17

编程热搜

目录