SpringSecurity 初始化流程源码

SpringSecurity 初始化流程源码

本篇主要讲解 SpringSecurity初始化流程的源码部分,包括核心的 springSecurityFilterChain 是如何创建的,以及在介绍哪里可以扩展个性化的配置,SpringSecurity源码其实是蛮难得 各种Builder Configure 看得真的头疼!

 1.简单介绍

 SpringSecurity 的核心功能主要包括:

 认证 (你是谁)
 授权 (你能干什么)
 攻击防护 (防止伪造身份)

 其核心就是一组过滤器链,项目启动后将会自动配置,本篇也会涉及过滤器链是如何自动初始化的。

Xnip20200118_195949.png

SecurityContextPersistenceFilter 是最前面的一个filter
 请求到它时候会去检查 根据sessionId找到session 判断session 中是否存在 SecurityContext 在 则将 SecurityContext 存入当前的线程中去
 响应的时候,看当前线程是否有SecurityContext ,如果有 放入到session中去 这样不同的请求都能拿到相同的 用户认证信息。

UsernamePasswordAuthenticationFilter 该过滤器是处理表单登录的,通过表单登录提交的认证都会经过它处理

SocialAuthenticationFilter 比如这个就是社交登录使用的Filter
 详细可以看我另外一篇 SpringSocial 实现第三方QQ登录SpringSocial 实现第三方QQ登录

绿色的过滤器都是可配置的,其他颜色的都不行!

 2.SecurityAutoConfiguration

 如果是SpringBoot项目只要你依赖了SpringSecurity相关依赖依然会有自动配置类
SecurityAutoConfiguration 生效 它会导入 WebSecurityEnableConfiguration

Xnip20200118_201432.png

 @EnableWebSecurity将会是我们本篇的主要切入点

Xnip20200118_201547.png

 3.@EnableWebSecurity注解介绍

 该注解 它是初始化Spring Security的入口 .

 打开@EnableWebSecurity注解

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
    SpringWebMvcImportSelector.class,
    OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {

/**
 * Controls debugging support for Spring Security. Default is false.
 * @return if true, enables debug support with Spring Security
 */
boolean debug() default false;
}

 该注解类通过@Configuration和@Import配合使用引入了一个配置类(WebSecurityConfiguration)和两个ImportSelector(SpringWebMvcImportSelector,OAuth2ImportSelector),我们重点关注下WebSecurityConfiguration,它是Spring Security的核心

 4.springSecurityFilterChain初始化流程及源码

 打开WebSecurityConfiguration 它是一个配置类,主要看 springSecurityFilterChain()方法,它就是初始化
springSecurityFilterChain的核心方法

/**
 * Creates the Spring Security Filter Chain
 * @return the {@link Filter} that represents the security filter chain
 * @throws Exception
 */
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    boolean hasConfigurers = webSecurityConfigurers != null
            && !webSecurityConfigurers.isEmpty();
    if (!hasConfigurers) {
        WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                .postProcess(new WebSecurityConfigurerAdapter() {
                });
        webSecurity.apply(adapter);
    }
    return webSecurity.build();
}

@Bean注解name属性值AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME就是XML中定义的springSecurityFilterChain

 从源码中知道过滤器通过最后的 webSecurity.build()创建,webSecurity的类型为:WebSecurity,它在 setFilterChainProxySecurityConfigurer方法中优先被创建了:

@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
        ObjectPostProcessor<Object> objectPostProcessor,
        @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
        throws Exception {
    webSecurity = objectPostProcessor
            .postProcess(new WebSecurity(objectPostProcessor));
    if (debugEnabled != null) {
        webSecurity.debug(debugEnabled);
    }

    webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);

    Integer previousOrder = null;
    Object previousConfig = null;
    for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
        Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
        if (previousOrder != null && previousOrder.equals(order)) {
            throw new IllegalStateException(
                    "@Order on WebSecurityConfigurers must be unique. Order of "
                            + order + " was already used on " + previousConfig + ", so it cannot be used on "
                            + config + " too.");
        }
        previousOrder = order;
        previousConfig = config;
    }
    for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
        webSecurity.apply(webSecurityConfigurer);
    }
    this.webSecurityConfigurers = webSecurityConfigurers;
}

 从代码中可以看到,它是直接被new出来的:

webSecurity = objectPostProcessor
            .postProcess(new WebSecurity(objectPostProcessor));

setFilterChainProxySecurityConfigurer 该方法的webSecurityConfigurers 参数是通过@Value注入的

@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}")

AutowiredWebSecurityConfigurersIgnoreParents的 getWebSecurityConfigurers()
 如下,就是获取所有的 WebSecurityConfigurer的类型的配置类
 而通常 我们通过继承 WebSecurityConfigurerAdapter 来自定义WebSecurityConfigurer

public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
    List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<>();
    Map<String, WebSecurityConfigurer> beansOfType = beanFactory
            .getBeansOfType(WebSecurityConfigurer.class);
    for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
        webSecurityConfigurers.add(entry.getValue());
    }
    return webSecurityConfigurers;
}

再回到setFilterChainProxySecurityConfigurer方法 下面有一段这样的代码 ,对于上面获取的所有的WebSecurityConfigurer类型 循环执行 webSecurity的apply方法

for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
        webSecurity.apply(webSecurityConfigurer);
    }

webSecurity集成AbstractConfiguredSecurityBuilder 它提供apply方法 再其内部调用add方法

public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
    add(configurer);
    return configurer;
}

add(configurer),主要就是将其传入的WebSecurityConfigurer存入到 LinkedHashMap configures中,
主要代码 this.configurers.put(clazz, configs);

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
    Assert.notNull(configurer, "configurer cannot be null");

    Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
            .getClass();
    synchronized (configurers) {
        if (buildState.isConfigured()) {
            throw new IllegalStateException("Cannot apply " + configurer
                    + " to already built object");
        }
        List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
                .get(clazz) : null;
        if (configs == null) {
            configs = new ArrayList<>(1);
        }
        configs.add(configurer);
        this.configurers.put(clazz, configs);
        if (buildState.isInitializing()) {
            this.configurersAddedInInitializing.add(configurer);
        }
    }
}

当所有的 WebSecurityConfigurer 类型的配置 全部应用到 WebSecurity中去后 setFilterChainProxySecurityConfigurer方法也就结束了


回到创建过滤器链的方法 springSecurityFilterChain()

 它会判断我们刚刚的webSecurityConfigurers是否存在,不存在就新建一个,然后执行 webSecurity.build() 重要!

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    boolean hasConfigurers = webSecurityConfigurers != null
            && !webSecurityConfigurers.isEmpty();
    if (!hasConfigurers) {
        WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                .postProcess(new WebSecurityConfigurerAdapter() {
                });
        webSecurity.apply(adapter);
    }
    return webSecurity.build();
}

最终内部会有下面这段代码, 主要关注 init() configure() 和 performBuild() 这三个方法

@Override
protected final O doBuild() throws Exception {
    synchronized (configurers) {
        buildState = BuildState.INITIALIZING;

        beforeInit();
        init();

        buildState = BuildState.CONFIGURING;

        beforeConfigure();
        configure();

        buildState = BuildState.BUILDING;

        O result = performBuild();

        buildState = BuildState.BUILT;

        return result;
    }
}

init() 内部循环遍历 所有的 WebSecurityConfigurer ,它会执行到 WebSecurityConfigurerAdapter的

private void init() throws Exception {
    Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

    for (SecurityConfigurer<O, B> configurer : configurers) {
        configurer.init((B) this);
    }

    for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
        configurer.init((B) this);
    }
}

configurer.init((B) this)

它只要完成两件重要的事情

初始化HttpSecurity对象(注意它和WebSecurity不一样 );
设置HttpSecurity对象添加至WebSecurity的securityFilterChainBuilders列表中;

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

初始化HttpSecurity对象在getHttp()方法中实现:

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);
    authenticationBuilder.authenticationEventPublisher(eventPublisher);
    Map<Class<?>, Object> sharedObjects = createSharedObjects();

    http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
            sharedObjects);
    if (!disableDefaults) {
        // @formatter:off
        http
            .csrf().and()
            .addFilter(new WebAsyncManagerIntegrationFilter())
            .exceptionHandling().and()
            .headers().and()
            .sessionManagement().and()
            .securityContext().and()
            .requestCache().and()
            .anonymous().and()
            .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;
}

 从代码中可以了解,HttpSecurity是直接被new出来的,在创建HttpSecurity之前,首先初始化了AuthenticationManagerBuilder对象,这里有段代码很重要就是: AuthenticationManager authenticationManager = authenticationManager();,它创建AuthenticationManager实例,打开authenticationManager()方法:

 默认实现是在 WebSecurityConfigurerAdapter 中

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    this.disableLocalConfigureAuthenticationBldr = true;
}

1、个性化配置入口之configure(AuthenticationManagerBuilder auth)

 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置AuthenticationManagerBuilder。

Xnip20200118_204438.png

如下是自己继承WebSecurityConfigurerAdapter 重写 configure(AuthenticationManagerBuilder auth),实现个性化的第一个配置入口

/**
* @author johnny
* @create 2020-01-18 下午6:40
**/
@Configuration
@Slf4j
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    super.configure(auth);
    log.info("【测试 定制化入口  configure(AuthenticationManagerBuilder auth)  的执行 】");
}
}

 构建完HttpSecurity实例后,默认情况下会添加默认的拦截其配置:

        http
            .csrf().and()
            .addFilter(new WebAsyncManagerIntegrationFilter())
            .exceptionHandling().and()
            .headers().and()
            .sessionManagement().and()
            .securityContext().and()
            .requestCache().and()
            .anonymous().and()
            .servletApi().and()
            .apply(new DefaultLoginPageConfigurer<>()).and()
            .logout();

 我挑一个默认的方法展开看一下比如 会话管理的sessionManagement(),内部就是去创建SessionManagementConfigurer并应用它

public SessionManagementConfigurer<HttpSecurity> sessionManagement() throws Exception {
    return getOrApply(new SessionManagementConfigurer<>());
}

 getOrApply 最有一句代码 return apply(configurer);

private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
        C configurer) throws Exception {
    C existingConfig = (C) getConfigurer(configurer.getClass());
    if (existingConfig != null) {
        return existingConfig;
    }
    return apply(configurer);
}

 apply(configurer) 注意这里的 configurer传入的是SessionManagementConfigurer

public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
        throws Exception {
    configurer.addObjectPostProcessor(objectPostProcessor);
    configurer.setBuilder((B) this);
    add(configurer);
    return configurer;
}

最终又调用了 add(configurer); 这不过这里是给 HttpSecurity的 configurers 配置初始的,上面是配置的WebSecurity的configurers, 不要混淆,最终这些configurers会被一个个创建成 对应的过滤器Filter的 详细在后面有说明

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
    Assert.notNull(configurer, "configurer cannot be null");

    Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
            .getClass();
    synchronized (configurers) {
        if (buildState.isConfigured()) {
            throw new IllegalStateException("Cannot apply " + configurer
                    + " to already built object");
        }
        List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
                .get(clazz) : null;
        if (configs == null) {
            configs = new ArrayList<>(1);
        }
        configs.add(configurer);
        this.configurers.put(clazz, configs);
        if (buildState.isInitializing()) {
            this.configurersAddedInInitializing.add(configurer);
        }
    }
}

 如下图:为HttpSecurity添加了很多默认的配置


Xnip20200118_205631.png

 回到 getHttp()方法

 最后调用configure(http);,这又是一个可个性化的配置入口,它的默认实现是:WebSecurityConfigurerAdapter提供的

 默认的配置是拦截所有的请求需要认证之后才能访问,如果没有认证,会自动生成一个认证表单要求输入用户名和密码。

protected 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();
}

2、个性化配置入口之configure(HttpSecurity http)
 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置HttpSecurity。

 OK,目前为止HttpSecurity已经被初始化,接下去需要设置HttpSecurity对象添加至WebSecurity的securityFilterChainBuilders列表中:

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

 当所有的WebSecurityConfigurer的init方法被调用之后,webSecurity.init()工作就结束了

 接下去调用了webSecurity.configure(),该方法同样是在AbstractConfiguredSecurityBuilder中实现的:

private void configure() throws Exception {
    Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

    for (SecurityConfigurer<O, B> configurer : configurers) {
        configurer.configure((B) this);
    }
}

 它的主要工作是迭代调用所有WebSecurityConfigurer的configurer方法,参数是WebSeucrity本身,这又是另外一个重要的个性化入口:

3、个性化配置入口之configure(WebSecurity web)
 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置WebSecurity。

 至此,三个重要的个性化入口都已经被调用,即在实现WebSecurityConfigurerAdapter经常需要重写的:

1、configure(AuthenticationManagerBuilder auth);

2、configure(WebSecurity web);

3、configure(HttpSecurity http);

 回到webSecurity构建过程,接下去重要的的调用:

O result = performBuild();

performBuild() 非常重要!!

@Override
protected Filter performBuild() throws Exception {
    Assert.state(
            !securityFilterChainBuilders.isEmpty(),
            () -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
                    + "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
                    + "More advanced users can invoke "
                    + WebSecurity.class.getSimpleName()
                    + ".addSecurityFilterChainBuilder directly");
    int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
    List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
            chainSize);
    for (RequestMatcher ignoredRequest : ignoredRequests) {
        securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
    }
    for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
        securityFilterChains.add(securityFilterChainBuilder.build());
    }
    FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
    if (httpFirewall != null) {
        filterChainProxy.setFirewall(httpFirewall);
    }
    filterChainProxy.afterPropertiesSet();

    Filter result = filterChainProxy;
    if (debugEnabled) {
        logger.warn("\n\n"
                + "********************************************************************\n"
                + "**********        Security debugging is enabled.       *************\n"
                + "**********    This may include sensitive information.  *************\n"
                + "**********      Do not use in a production system!     *************\n"
                + "********************************************************************\n\n");
        result = new DebugFilter(filterChainProxy);
    }
    postBuildAction.run();
    return result;


}

 首先计算出chainSize,也就是ignoredRequests.size() + securityFilterChainBuilders.size();,如果你不配置ignoredRequests,那就是securityFilterChainBuilders.size(),也就是HttpSecurity的个数,其本质上就是你一共配置几个WebSecurityConfigurerAdapter,因为每个WebSecurityConfigurerAdapter对应一个HttpSecurity,而所谓的ignoredRequests就是FilterChainProxy的请求,默认是没有的,如果你需要条跳过某些请求不需要认证或授权,可以如下配置:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/statics/**");
}

 在上面配置中,所有以/statics开头请求都将被FilterChainProxy忽略。

 securityFilterChains.add(securityFilterChainBuilder.build()); 这一行就是初始化所有的过滤器,记得上面有段代码如下,将HttpSecurity设置到WebSecurity的 securityFilterChainBuilder中,上面就是调用HttpSecurity.build()方法,初始化所有的 HttpSecurity的过滤器链

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

 依然来到 doBuild()方法,只不过这次是执行的 HttpSecurity的

@Override
protected final O doBuild() throws Exception {
    synchronized (configurers) {
        buildState = BuildState.INITIALIZING;

        beforeInit();
        init();

        buildState = BuildState.CONFIGURING;

        beforeConfigure();
        configure();

        buildState = BuildState.BUILDING;

        O result = performBuild();

        buildState = BuildState.BUILT;

        return result;
    }
}

 重点查看 configure()该方法 会调用对应的 过滤器配置的configure()
如 再内部创建 SessionManagementFilter 最后添加到HttpSecurity中,也就是拿 HttpSecurity的configures 一个个创建出对应的过滤器


Xnip20200118_205631.png
@Override
public void configure(H http) {
    SecurityContextRepository securityContextRepository = http
            .getSharedObject(SecurityContextRepository.class);
    SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(
            securityContextRepository, getSessionAuthenticationStrategy(http));
    if (this.sessionAuthenticationErrorUrl != null) {
        sessionManagementFilter.setAuthenticationFailureHandler(
                new SimpleUrlAuthenticationFailureHandler(
                        this.sessionAuthenticationErrorUrl));
    }
    InvalidSessionStrategy strategy = getInvalidSessionStrategy();
    if (strategy != null) {
        sessionManagementFilter.setInvalidSessionStrategy(strategy);
    }
    AuthenticationFailureHandler failureHandler = getSessionAuthenticationFailureHandler();
    if (failureHandler != null) {
        sessionManagementFilter.setAuthenticationFailureHandler(failureHandler);
    }
    AuthenticationTrustResolver trustResolver = http
            .getSharedObject(AuthenticationTrustResolver.class);
    if (trustResolver != null) {
        sessionManagementFilter.setTrustResolver(trustResolver);
    }
    sessionManagementFilter = postProcess(sessionManagementFilter);

    http.addFilter(sessionManagementFilter);
    if (isConcurrentSessionControlEnabled()) {
        ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);

        concurrentSessionFilter = postProcess(concurrentSessionFilter);
        http.addFilter(concurrentSessionFilter);
    }
}

 当doBuild()中的 configure();执行完毕后 的会得到如下HttpSecurity可以看到它内部的filters已经全部创建完毕

Xnip20200118_211830.png

 回到doBuild()方法 该方中有 performBuild() 调用HttpSecurity的 performBuild(),默认实现如下,先对上面所有的过滤器进行排序,使用的是 FilterComparator() 进行排序的,这里不展开了,反正就是会排序成文章开始的那张图上面的顺序

@Override
protected DefaultSecurityFilterChain performBuild() {
    filters.sort(comparator);
    return new DefaultSecurityFilterChain(requestMatcher, filters);
}

 最后返回的是SecurityFilterChain的默认实现DefaultSecurityFilterChain。

 构建完所有SecurityFilterChain后,创建最为重要的FilterChainProxy实例,

FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
Xnip20200118_212246.png

 至此Spring Security 初始化完成,包括springSecurityFilterChain初始化,我们通过继承WebSecurityConfigurerAdapter来代达到个性化配置目的,文中提到了三个重要的个性化入口,并且WebSecurityConfigurerAdapter是可以配置多个的,其对应的接口就是会存在多个SecurityFilterChain实例,但是它们人仍然在同一个FilterChainProxy中,通过RequestMatcher来匹配并传入到对应的SecurityFilterChain中执行请求。

 5.个性化入口配置(扩展WebSecurityConfigurerAdapter)

 重要的个性化入口都是哪里调用的 已经在上面初始化 springSecurityFilterChain 源码中讲解了,这里知识总结一下

1、个性化配置入口之configure(AuthenticationManagerBuilder auth)

 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置AuthenticationManagerBuilder。

2、个性化配置入口之configure(HttpSecurity http)
 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置HttpSecurity。

3、个性化配置入口之configure(WebSecurity web)
 我们可以通过继承WebSecurityConfigurerAdapter并重写该方法来个性化配置WebSecurity。

 实现WebSecurityConfigurerAdapter经常需要重写的:

1、configure(AuthenticationManagerBuilder auth);

2、configure(WebSecurity web);

3、configure(HttpSecurity http);

 6.总结

本篇主要讲解了
 1.SpringBoot对于SpringSecurity的自动配置的支持类SecurityAutoConfiguration,
 2.核心注解@EnableWebSecurity
 3. SpringSecurity的核心过滤器链 springSecurityFilterChain 的初始化流程的源码
源码部分还是定下心来多看 加油!

个人博客网站 https://www.askajohnny.com 欢迎来访问!
本文由博客一文多发平台 OpenWrite 发布!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容