成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring Security 初始化流程詳解

tommego / 1732人閱讀

摘要:構(gòu)建完實(shí)例后,將它設(shè)置為的父認(rèn)證管理器并將該傳入構(gòu)造器構(gòu)建實(shí)例。,目前為止已經(jīng)被初始化,接下去需要設(shè)置對(duì)象添加至的列表中打開類結(jié)構(gòu),和一樣,它也實(shí)現(xiàn)了接口,同樣繼承自。最后返回的是的默認(rèn)實(shí)現(xiàn)。

最近在整合微服務(wù)OAuth 2認(rèn)證過程中,它是基于Spring Security之上,而本人對(duì)Spring Security架構(gòu)原理并不太熟悉,導(dǎo)致很多配置搞不太清楚,遂咬牙啃完了Spring Security核心源碼,花了差不多一星期,總體上來說,其代碼確實(shí)比較晦澀,之前在學(xué)習(xí)Apache Shiro框架之前也曾經(jīng)在相關(guān)論壇里了解過,相比Spring Security,Apache Shiro真的是相當(dāng)輕量,代碼研讀起來容易很多,而Spring Security類繼承結(jié)構(gòu)復(fù)雜,大量使用了其所謂Builder和Configuer模式,其代碼跟蹤過程很痛苦,遂記錄下,分享給有需要的人,由于本人能力有限,在文章中有不對(duì)之處,還請(qǐng)各位執(zhí)教,在此謝謝各位了。

本人研讀的Spring Security版本為:5.1.4.RELEASE

Spring Security在3.2版本之后支持Java Configuration,即:通過Java編碼形式配置Spring Security,可不再依賴XML文件配置,本文采用Java Configuration方式。

在Spring Security官方文檔中有一個(gè)最簡配置例子:

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

我們先不要看其它內(nèi)容,先關(guān)注注解@EnableWebSecurity,它是初始化Spring Security的入口,打開其源碼如下:

@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配合使用引入了一個(gè)配置類(WebSecurityConfiguration)和兩個(gè)ImportSelector(SpringWebMvcImportSelector,OAuth2ImportSelector),我們重點(diǎn)關(guān)注下WebSecurityConfiguration,它是Spring Security的核心,正是它構(gòu)建初始化了所有的Bean實(shí)例和相關(guān)配置,下面我們?cè)敿?xì)分析下。

打開WebSecurityConfiguration源碼,發(fā)現(xiàn)它被@Configuration標(biāo)記,說明它是配置類,

@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware 

該類中最重要的工作就是實(shí)例并注冊(cè)FilterChainProxy,也就是我們?cè)谝郧癤ML文件中配置的過濾器:


    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy


    springSecurityFilterChain
    /*

該過濾器負(fù)責(zé)攔截請(qǐng)求,并把請(qǐng)求通過一定的匹配規(guī)則(通過RequestMatcher匹配實(shí)現(xiàn))路由(或者Delegate)到具體的SecurityFilterChain,源碼如下:

/**
     * 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()創(chuàng)建,webSecurity的類型為:WebSecurity,它在setFilterChainProxySecurityConfigurer方法中優(yōu)先被創(chuàng)建了:

    /**
     * Sets the {@code }
     * instances used to create the web configuration.
     *
     * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a
     * {@link WebSecurity} instance
     * @param webSecurityConfigurers the
     * {@code } instances used to
     * create the web configuration
     * @throws Exception
     */
    @Autowired(required = false)
    public void setFilterChainProxySecurityConfigurer(
            ObjectPostProcessor objectPostProcessor,
            @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers)
            throws Exception {
        webSecurity = objectPostProcessor
                .postProcess(new WebSecurity(objectPostProcessor));
        if (debugEnabled != null) {
            webSecurity.debug(debugEnabled);
        }

        Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);

        Integer previousOrder = null;
        Object previousConfig = null;
        for (SecurityConfigurer 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 webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }
        this.webSecurityConfigurers = webSecurityConfigurers;
    }

從代碼中可以看到,它是直接被new出來的:

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

setFilterChainProxySecurityConfigurer方法參數(shù)中需要被注入兩個(gè)對(duì)象:objectPostProcessorwebSecurityConfigurersobjectPostProcessor是在ObjectPostProcessorConfiguration配置類中注冊(cè)的,而webSecurityConfigurers則是使用了@Value注解方式,注解內(nèi)容為:#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()},通過源碼了解,autowiredWebSecurityConfigurersIgnoreParents是在本類中被注冊(cè):

@Bean
    public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
            ConfigurableListableBeanFactory beanFactory) {
        return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
    }

在AutowiredWebSecurityConfigurersIgnoreParents中定義了方法:getWebSecurityConfigurers

@SuppressWarnings({ "rawtypes", "unchecked" })
    public List> getWebSecurityConfigurers() {
        List> webSecurityConfigurers = new ArrayList>();
        Map beansOfType = beanFactory
                .getBeansOfType(WebSecurityConfigurer.class);
        for (Entry entry : beansOfType.entrySet()) {
            webSecurityConfigurers.add(entry.getValue());
        }
        return webSecurityConfigurers;
    }

它通過BeanFactory獲取了類型為WebSecurityConfigurer的Bean實(shí)例列表?;氐?b>WebSecurityConfiguration類中的setFilterChainProxySecurityConfigurer方法,它把WebSecurityConfigurer列表設(shè)置到了WebSecurity中,源碼如下:

for (SecurityConfigurer webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }

通過apply方法,apply方法其實(shí)就是webSecurityConfigurer放入webSecurity維護(hù)的configurers屬性中,configurers是個(gè)LinkedHashMap,源碼如下:

    /**
     * Applies a {@link SecurityConfigurer} to this {@link SecurityBuilder} overriding any
     * {@link SecurityConfigurer} of the exact same class. Note that object hierarchies
     * are not considered.
     *
     * @param configurer
     * @return the {@link SecurityConfigurerAdapter} for further customizations
     * @throws Exception
     */
    public > C apply(C configurer) throws Exception {
        add(configurer);
        return configurer;
    }

其中代碼add(configurer)就是將這些webSecurityConfigurer添加到webSecurityconfigurers屬性中。

現(xiàn)在webSecurity的初始化工作已經(jīng)完成,現(xiàn)在回到springSecurityFilterChain方法中,它首先檢查當(dāng)前是否配置了webSecurityConfigurer,如果沒有的會(huì)默認(rèn)設(shè)置一個(gè),并且調(diào)用上面提到的apply方法,源碼如下:

        boolean hasConfigurers = webSecurityConfigurers != null
                && !webSecurityConfigurers.isEmpty();
        if (!hasConfigurers) {
            WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                    .postProcess(new WebSecurityConfigurerAdapter() {
                    });
            webSecurity.apply(adapter);
        }

如果已經(jīng)存在配置了webSecurityConfigurer,則調(diào)用webSecurity.build()進(jìn)行構(gòu)建。

在進(jìn)入build方法之前,首先簡單介紹下WebSecurity的繼承結(jié)構(gòu),

它實(shí)現(xiàn)了SecurityBuilder接口,繼承自AbstractConfiguredSecurityBuilder,AbstractConfiguredSecurityBuilder繼承自AbstractSecurityBuilderAbstractSecurityBuilder實(shí)現(xiàn)了SecurityBuilder,其中AbstractConfiguredSecurityBuilder實(shí)現(xiàn)了通過自定義SecurityConfigurer類來配置SecurityBuilder,上面提到的apply(SecurityConfigurer configurer)就是在該類中實(shí)現(xiàn)的,它把configurer保存在它維護(hù)的LinkedHashMap>, List>> configurers = new LinkedHashMap>, List>>()中。

調(diào)用webSecurity.build()后,首先調(diào)用的父類AbstractSecurityBuilder中的build方法:

public final O build() throws Exception {
        if (this.building.compareAndSet(false, true)) {
            this.object = doBuild();
            return this.object;
        }
        throw new AlreadyBuiltException("This object has already been built");
    }

然后調(diào)用doBuild()doBuild()在子類中實(shí)現(xiàn),AbstractConfiguredSecurityBuilder實(shí)現(xiàn)了該方法:

    @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;
        }
    }

在這里重點(diǎn)關(guān)注init()、configure()performBuild(),下面逐個(gè)分析它們的作用。

init()方法在AbstractConfiguredSecurityBuilder實(shí)現(xiàn):

private void init() throws Exception {
        Collection> configurers = getConfigurers();

        for (SecurityConfigurer configurer : configurers) {
            configurer.init((B) this);
        }

        for (SecurityConfigurer configurer : configurersAddedInInitializing) {
            configurer.init((B) this);
        }
    }

它的工作是迭代調(diào)用所有配置的SecurityConfigrerinit方法,在這里其實(shí)是它的子類WebSecurityConfigurer,因?yàn)橹矮@取時(shí)指定的類型就是WebSecurityConfigurer,在上文中提到AutowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()中:

Map beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class);

而實(shí)現(xiàn)了WebSecurityConfigurer接口的就是WebSecurityConfigurerAdapter,WebSecurityConfigurerAdapter.init()源碼如下:

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

它只要完成兩件重要的事情:

初始化HttpSecurity對(duì)象;

設(shè)置HttpSecurity對(duì)象添加至WebSecuritysecurityFilterChainBuilders列表中;

初始化HttpSecurity對(duì)象在getHttp()方法中實(shí)現(xiàn):

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, 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 defaultHttpConfigurers =
                    SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);

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

從代碼中可以了解,HttpSecurity是直接被new出來的,在創(chuàng)建HttpSecurity之前,首先初始化了AuthenticationManagerBuilder對(duì)象,這里有段代碼很重要就是: AuthenticationManager authenticationManager = authenticationManager();,它創(chuàng)建AuthenticationManager實(shí)例,打開authenticationManager()方法:

protected AuthenticationManager authenticationManager() throws Exception {
        if (!authenticationManagerInitialized) {
            configure(localConfigureAuthenticationBldr);
            if (disableLocalConfigureAuthenticationBldr) {
                authenticationManager = authenticationConfiguration
                        .getAuthenticationManager();
            }
            else {
                authenticationManager = localConfigureAuthenticationBldr.build();
            }
            authenticationManagerInitialized = true;
        }
        return authenticationManager;
    }

在初始化時(shí),它會(huì)調(diào)用configure(localConfigureAuthenticationBldr);,默認(rèn)的實(shí)現(xiàn)是:

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

【1、個(gè)性化配置入口之configure(AuthenticationManagerBuilder auth)
我們可以通過繼承WebSecurityConfigurerAdapter并重寫該方法來個(gè)性化配置AuthenticationManager

構(gòu)建完authenticationManager 實(shí)例后,將它設(shè)置為authenticationBuilder的父認(rèn)證管理器:

authenticationBuilder.parentAuthenticationManager(authenticationManager);

并將該authenticationBuilder傳入HttpSecurity構(gòu)造器構(gòu)建HttpSecurity實(shí)例。

構(gòu)建完HttpSecurity實(shí)例后,默認(rèn)情況下會(huì)添加默認(rèn)的攔截其配置:

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

最后調(diào)用configure(http);,這又是一個(gè)可個(gè)性化的配置入口,它的默認(rèn)實(shí)現(xiàn)是:

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

默認(rèn)的配置是攔截所有的請(qǐng)求需要認(rèn)證之后才能訪問,如果沒有認(rèn)證,會(huì)自動(dòng)生成一個(gè)認(rèn)證表單要求輸入用戶名和密碼。
【2、個(gè)性化配置入口之configure(HttpSecurity http)
我們可以通過繼承WebSecurityConfigurerAdapter并重寫該方法來個(gè)性化配置HttpSecurity。

OK,目前為止HttpSecurity已經(jīng)被初始化,接下去需要設(shè)置HttpSecurity對(duì)象添加至WebSecuritysecurityFilterChainBuilders列表中:

web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
            public void run() {
                FilterSecurityInterceptor securityInterceptor = http
                        .getSharedObject(FilterSecurityInterceptor.class);
                web.securityInterceptor(securityInterceptor);
            }
        });

打開HttpSecurity類結(jié)構(gòu),和WebSecurity一樣,它也實(shí)現(xiàn)了SecurityBuilder接口,同樣繼承自AbstractConfiguredSecurityBuilder。

當(dāng)所有的WebSecurityConfigurerinit方法被調(diào)用之后,webSecurity.init()工作就結(jié)束了。
接下去調(diào)用了webSecurity.configure(),該方法同樣是在AbstractConfiguredSecurityBuilder中實(shí)現(xiàn)的:

private void configure() throws Exception {
        Collection> configurers = getConfigurers();

        for (SecurityConfigurer configurer : configurers) {
            configurer.configure((B) this);
        }
    }

它的主要工作是迭代調(diào)用所有WebSecurityConfigurerconfigurer方法,參數(shù)是WebSeucrity本身,這又是另外一個(gè)重要的個(gè)性化入口:
【3、個(gè)性化配置入口之configure(WebSecurity web)
我們可以通過繼承WebSecurityConfigurerAdapter并重寫該方法來個(gè)性化配置WebSecurity。

自此,三個(gè)重要的個(gè)性化入口都已經(jīng)被調(diào)用,即在實(shí)現(xiàn)WebSecurityConfigurerAdapter經(jīng)常需要重寫的:

1、configure(AuthenticationManagerBuilder auth);

2、configure(WebSecurity web);

3、configure(HttpSecurity http);

回到webSecurity構(gòu)建過程,接下去重要的的調(diào)用:

O result = performBuild();

該方法在WebSecurityConfigurerAdapter中實(shí)現(xiàn),返回的就是過濾器FilterChainProxy,源碼如下:

@Override
    protected Filter performBuild() throws Exception {
        Assert.state(
                !securityFilterChainBuilders.isEmpty(),
                () -> "At least one SecurityBuilder 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 securityFilterChains = new ArrayList<>(
                chainSize);
        for (RequestMatcher ignoredRequest : ignoredRequests) {
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
        }
        for (SecurityBuilder 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("

"
                    + "********************************************************************
"
                    + "**********        Security debugging is enabled.       *************
"
                    + "**********    This may include sensitive information.  *************
"
                    + "**********      Do not use in a production system!     *************
"
                    + "********************************************************************

");
            result = new DebugFilter(filterChainProxy);
        }
        postBuildAction.run();
        return result;
    }

首先計(jì)算出chainSize,也就是ignoredRequests.size() + securityFilterChainBuilders.size();,如果你不配置ignoredRequests,那就是securityFilterChainBuilders.size(),也就是HttpSecurity的個(gè)數(shù),其本質(zhì)上就是你一共配置幾個(gè)WebSecurityConfigurerAdapter,因?yàn)槊總€(gè)WebSecurityConfigurerAdapter對(duì)應(yīng)一個(gè)HttpSecurity,而所謂的ignoredRequests就是FilterChainProxy的請(qǐng)求,默認(rèn)是沒有的,如果你需要條跳過某些請(qǐng)求不需要認(rèn)證或授權(quán),可以如下配置:

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

在上面配置中,所有以/statics開頭請(qǐng)求都將被FilterChainProxy忽略。

計(jì)算完chainSize后,就會(huì)創(chuàng)建List securityFilterChains = new ArrayList<>(chainSize);,遍歷所有的HttpSecurity,調(diào)用HtppSecuritybuild()構(gòu)建其對(duì)應(yīng)的過濾器鏈SecurityFilterChain實(shí)例,并將SecurityFilterChain添加到securityFilterChains 列表中:

for (SecurityBuilder securityFilterChainBuilder : securityFilterChainBuilders) {
            securityFilterChains.add(securityFilterChainBuilder.build());
        }

調(diào)用HtppSecuritybuild()構(gòu)建其實(shí)和調(diào)用WebSecuritybuild()構(gòu)建類類似,父類中方法一次被執(zhí)行,最后執(zhí)行本身的performBuild()方法,其源碼如下:

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

構(gòu)建SecurityFilterChain主要是完成RequestMatcher和對(duì)應(yīng)的過濾器列表,我們都知道在Spring Security中,過濾器執(zhí)行按順序順序的,這個(gè)排序就是在performBuild()中完成的,也就是:

Collections.sort(filters, comparator);

它通過一個(gè)比較器實(shí)現(xiàn)了過濾器的排序,這個(gè)比較器就是FilterComparator,有興趣的朋友可以自己去了解詳情。
最后返回的是SecurityFilterChain的默認(rèn)實(shí)現(xiàn)DefaultSecurityFilterChain

構(gòu)建完所有SecurityFilterChain后,創(chuàng)建最為重要的FilterChainProxy實(shí)例,

FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);

構(gòu)造器中傳入SecurityFilterChain列表,如果開啟了Debug模式,還會(huì)被包裝成DebugFilter類型,共開發(fā)調(diào)試使用,默認(rèn)是關(guān)閉的,可以通過過下面方式開啟Debug模式:

@Override
    public void configure(WebSecurity web) throws Exception {
        web.debug(true);
    }

至此Spring Security 初始化完成,我們通過繼承WebSecurityConfigurerAdapter來代達(dá)到個(gè)性化配置目的,文中提到了三個(gè)重要的個(gè)性化入口,并且WebSecurityConfigurerAdapter是可以配置多個(gè)的,其對(duì)應(yīng)的接口就是會(huì)存在多個(gè)SecurityFilterChain實(shí)例,但是它們?nèi)巳匀辉谕粋€(gè)FilterChainProxy中,通過RequestMatcher來匹配并傳入到對(duì)應(yīng)的SecurityFilterChain中執(zhí)行請(qǐng)求。

(全文完)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74483.html

相關(guān)文章

  • spring security使用詳解

    摘要:使用詳解由于公司新的后臺(tái)項(xiàng)目獨(dú)立,和其他服務(wù)沒有關(guān)系,所以考慮單獨(dú)實(shí)現(xiàn)自己的用戶登錄模塊。表單登錄具體流程如下圖本文參考地址 spring security使用詳解 由于公司新的后臺(tái)項(xiàng)目獨(dú)立,和其他服務(wù)沒有關(guān)系,所以考慮單獨(dú)實(shí)現(xiàn)自己的用戶登錄模塊。 所以,我將對(duì)spring security基于 springboot 框架的使用方式總結(jié)如下: (1)當(dāng)我們?cè)趐om文件中,添加...

    woshicixide 評(píng)論0 收藏0
  • spring security使用詳解

    摘要:使用詳解由于公司新的后臺(tái)項(xiàng)目獨(dú)立,和其他服務(wù)沒有關(guān)系,所以考慮單獨(dú)實(shí)現(xiàn)自己的用戶登錄模塊。表單登錄具體流程如下圖本文參考地址 spring security使用詳解 由于公司新的后臺(tái)項(xiàng)目獨(dú)立,和其他服務(wù)沒有關(guān)系,所以考慮單獨(dú)實(shí)現(xiàn)自己的用戶登錄模塊。 所以,我將對(duì)spring security基于 springboot 框架的使用方式總結(jié)如下: (1)當(dāng)我們?cè)趐om文件中,添加...

    isLishude 評(píng)論0 收藏0
  • 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》

    摘要:下一代服務(wù)端開發(fā)下一代服務(wù)端開發(fā)第部門快速開始第章快速開始環(huán)境準(zhǔn)備,,快速上手實(shí)現(xiàn)一個(gè)第章企業(yè)級(jí)服務(wù)開發(fā)從到語言的缺點(diǎn)發(fā)展歷程的缺點(diǎn)為什么是產(chǎn)生的背景解決了哪些問題為什么是的發(fā)展歷程容器的配置地獄是什么從到下一代企業(yè)級(jí)服務(wù)開發(fā)在移動(dòng)開發(fā)領(lǐng)域 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》 Kotlin + Spring Boot : 下一代 Java...

    springDevBird 評(píng)論0 收藏0
  • 分布式配置中心:Spring Cloud Config

    摘要:根據(jù)自己維護(hù)的倉庫信息和客戶端傳遞過來的配置定位信息去查找配置信息。通過命令將找到的配置信息下載到的文件系統(tǒng)中。該配置內(nèi)容的優(yōu)先級(jí)高于包內(nèi)部的配置內(nèi)容,在包中重復(fù)的內(nèi)容將不會(huì)被加載。在中配置注冊(cè)中心地址。 構(gòu)建配置中心 創(chuàng)建一個(gè)基礎(chǔ)Spring Boot工程,命名為config-server,并在pom.xml中引入以下依賴: org.spri...

    ckllj 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

tommego

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<