再次深入理解 Spring Security 的强大功能

再次深入理解 Spring Security 的强大功能

松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里–>Spring Boot+Vue+微人事视频教程

我们来继

续撸 Spring Security 源码。

SecurityConfigurer 在 Spring Security 中是一个非常重要的角色。在前面的文章中,松哥曾经多次提到过,Spring Security 过滤器链中的每一个过滤器,都是通过 xxxConfigurer 来进行配置的,而这些 xxxConfigurer 实际上都是 SecurityConfigurer 的实现。

所以我们今天有必要来跟大家把 SecurityConfigurer 从头到尾捋一捋。

  1. SecurityConfigurer
    SecurityConfigurer 本身是一个接口,我们来看下:
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;
  }
 }
}

这两个方法松哥之前都有给大家介绍过,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,最终效果是一样的)。
《https://www.imdb.com/list/ls085241039/》
《https://www.imdb.com/list/ls085243092/》
《https://www.imdb.com/list/ls085243510/》
《https://www.imdb.com/list/ls085243520/》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值