最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringSecurity的@EnableWebSecurity注解詳解

 更新時間:2023年11月21日 10:10:08   作者:dalianpai  
這篇文章主要介紹了SpringSecurity的@EnableWebSecurity注解詳解,@EnableWebSecurity是開啟SpringSecurity的默認(rèn)行為,它的上面有一個Import注解導(dǎo)入了WebSecurityConfiguration類,就是往IOC容器中注入了WebSecurityConfiguration這個類,需要的朋友可以參考下

@EnableWebSecurity

@EnableWebSecurity是開啟SpringSecurity的默認(rèn)行為,它的上面有一個Import注解導(dǎo)入了WebSecurityConfiguration類,也就是說我們加上了@EnableWebSecurity這個注解,就是往IOC容器中注入了WebSecurityConfiguration這個類。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    boolean debug() default false;
}

它還有一個debug的功能,如果設(shè)置為true,則開啟debug功能,每個經(jīng)過那些過濾器都會被展示出來。

image-20210808122218037

WebSecurityConfiguration

WebSecurityConfiguration用來配置初始化webSecurity的,在setFilterChainProxySecurityConfigurer方法中,它以配置SpringSecurity時繼承自WebSecurityConfigurerAdapter的配置類來初始化SecurityConfigurer列表,來啟用所需的安全策略

@Autowired(
        required = false
    )
    public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
        this.webSecurity = (WebSecurity)objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
        if (this.debugEnabled != null) {
            this.webSecurity.debug(this.debugEnabled);
        }
 
        webSecurityConfigurers.sort(WebSecurityConfiguration.AnnotationAwareOrderComparator.INSTANCE);
        Integer previousOrder = null;
        Object previousConfig = null;
 
        Iterator var5;
        SecurityConfigurer config;
        for(var5 = webSecurityConfigurers.iterator(); var5.hasNext(); previousConfig = config) {
            config = (SecurityConfigurer)var5.next();
            Integer order = WebSecurityConfiguration.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;
        }
 
        var5 = webSecurityConfigurers.iterator();
 
        while(var5.hasNext()) {
            config = (SecurityConfigurer)var5.next();
            //將配置的每一個SecurityConfigurer列表傳遞給 webSecurity
            this.webSecurity.apply(config);
        }
 
        this.webSecurityConfigurers = webSecurityConfigurers;
    }

WebSecurityConfiguration這個類的創(chuàng)建流程也是經(jīng)過spring容器初始化的那一整套。

image-20210808131543640

因為我們配置的SpringSecurityConfig這個類,繼承了WebSecurityConfigurerAdapter,它又實現(xiàn)了SecurityConfigurer這個接口,所以在配置的時候,能拿到我們這個配置類里面的信息,具體如圖:

image-20210808133759715

創(chuàng)建過濾器鏈

//提供一個名叫springSecurityFilterChain的bean,返回一個Filter對象
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
             //如果沒有配置過Spring Security,則會議WebSecurityConfigurerAdapter中的配置作為默認(rèn),上面能拿到我們的配置,因此就不走這段邏輯
			WebSecurityConfigurerAdapter
WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
		return webSecurity.build();
	}

以前在Spring的配置中,會有一個web.xml,在里面配置過濾器,但是現(xiàn)在SpringBoot已經(jīng)自動配置了web.xml. DelegatingFilterProxy是Spring提供的一個標(biāo)準(zhǔn)Servlet Filter代理,并代理改bean提供的過濾器,也就是說,在這個配置中,最終起作用的過濾器是什么完全取決于springSecurityFilterChain。

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(SecurityProperties.class)
@ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class })
@AutoConfigureAfter(SecurityAutoConfiguration.class)
public class SecurityFilterAutoConfiguration {
 
	private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;
 
	@Bean
	@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
	public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(
			SecurityProperties securityProperties) {
		DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
				DEFAULT_FILTER_NAME);
		registration.setOrder(securityProperties.getFilter().getOrder());
		registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
		return registration;
	}
 
	private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
		if (securityProperties.getFilter().getDispatcherTypes() == null) {
			return null;
		}
		return securityProperties.getFilter().getDispatcherTypes().stream()
				.map((type) -> DispatcherType.valueOf(type.name()))
				.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
	}
 
}

前面說的springSecurityFilterChain是由 webSecurity.build()這個創(chuàng)建的,最終調(diào)用的是doBuild方法,是由AbstractConfiguredSecurityBuilder提供的

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

AbstractConfiguredSecurityBuilder的doBuild調(diào)用的是WebSecurity的performBuild()方法

@Override
	protected final O doBuild() throws Exception {
		synchronized (configurers) {
            //安裝狀態(tài)依次執(zhí)行相應(yīng)的方法
			buildState = BuildState.INITIALIZING;
 
			beforeInit();
            //初始化狀態(tài),通過調(diào)用WebSecurityConfigurerAdapter的init,將所有HttpSecurity添加到WebSecurity里
			init();
 
			buildState = BuildState.CONFIGURING;
 
			beforeConfigure();
			configure();
 
			buildState = BuildState.BUILDING;
      //在BUILDING階段調(diào)用WebSecurity的performBuild方法
			O result = performBuild();
 
			buildState = BuildState.BUILT;
 
			return result;
		}
	}

在init方法中,初始化狀態(tài),通過調(diào)用WebSecurityConfigurerAdapter的init,將所有HttpSecurity添加到WebSecurity里

image-20210808135049557

在performBuild方法中,SpringSecurity完成了所有過濾器的創(chuàng)建,最終返回一個過濾器鏈代理類filterChainProxy.

@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));
		}
         //簡單來說,就是每一個HttpSecurity生成一個過濾器鏈,HttpSecurity則來自我們配置的WebSecurityConfigure
		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;
	}

image-20210808134236782

filterChainProxy間接繼承了FIlter,可以作為真正的過濾器使用,它會攜帶若干條過濾器鏈,并在承擔(dān)過濾器職責(zé)時,將其派發(fā)到所有過濾器鏈的每一個過濾器上。

@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
		if (clearContext) {
			try {
				request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
				doFilterInternal(request, response, chain);
			}
			finally {
				SecurityContextHolder.clearContext();
				request.removeAttribute(FILTER_APPLIED);
			}
		}
		else {
			doFilterInternal(request, response, chain);
		}
	}

doFilterInternal是真正執(zhí)行虛擬過濾器鏈邏輯的方法

private void doFilterInternal(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
    //附上Spring Security提供的HTTP防火墻
		FirewalledRequest fwRequest = firewall
				.getFirewalledRequest((HttpServletRequest) request);
		HttpServletResponse fwResponse = firewall
				.getFirewalledResponse((HttpServletResponse) response);
     //按照配置的RequestMatcher,決定每一個請求會經(jīng)過那些過濾器
		List<Filter> filters = getFilters(fwRequest);
 
		if (filters == null || filters.size() == 0) {
			if (logger.isDebugEnabled()) {
				logger.debug(UrlUtils.buildRequestUrl(fwRequest)
						+ (filters == null ? " has no matching filters"
								: " has an empty filter list"));
			}
 
			fwRequest.reset();
 
			chain.doFilter(fwRequest, fwResponse);
 
			return;
		}
             //所有的過濾器合并成一條虛擬的過濾器鏈
		VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
           //模擬過濾器的執(zhí)行流程,執(zhí)行整條過濾器鏈
		vfc.doFilter(fwRequest, fwResponse);
	}
 
private static class VirtualFilterChain implements FilterChain {
		private final FilterChain originalChain;
		private final List<Filter> additionalFilters;
		private final FirewalledRequest firewalledRequest;
		private final int size;
		private int currentPosition = 0;
 
		private VirtualFilterChain(FirewalledRequest firewalledRequest,
				FilterChain chain, List<Filter> additionalFilters) {
			this.originalChain = chain;
			this.additionalFilters = additionalFilters;
			this.size = additionalFilters.size();
			this.firewalledRequest = firewalledRequest;
		}
 
		@Override
		public void doFilter(ServletRequest request, ServletResponse response)
				throws IOException, ServletException {
			if (currentPosition == size) {
				if (logger.isDebugEnabled()) {
					logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
							+ " reached end of additional filter chain; proceeding with original chain");
				}
 
				// Deactivate path stripping as we exit the security filter chain
				this.firewalledRequest.reset();
                               執(zhí)行過濾器鏈后,調(diào)用真實的FilterChain,完成原生過濾器的剩余邏輯
				originalChain.doFilter(request, response);
			}
			else {
				currentPosition++;
 
				Filter nextFilter = additionalFilters.get(currentPosition - 1);
 
				if (logger.isDebugEnabled()) {
					logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
							+ " at position " + currentPosition + " of " + size
							+ " in additional filter chain; firing Filter: '"
							+ nextFilter.getClass().getSimpleName() + "'");
				}
                              //通過改變下表回調(diào)的方式,按照順序執(zhí)行每一個過濾器
				nextFilter.doFilter(request, response, this);
			}
		}
	}

image-20210808132205008

image-20210808132636043

到此這篇關(guān)于SpringSecurity的@EnableWebSecurity注解詳解的文章就介紹到這了,更多相關(guān)@EnableWebSecurity注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot+maven多環(huán)境動態(tài)配置及編譯失敗的解決方案(步驟詳解)

    springboot+maven多環(huán)境動態(tài)配置及編譯失敗的解決方案(步驟詳解)

    這篇文章主要介紹了springboot+maven多環(huán)境動態(tài)配置及編譯失敗的解決方案,本文通過實例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • Java排序算法之計數(shù)排序解析

    Java排序算法之計數(shù)排序解析

    這篇文章主要介紹了Java排序算法之計數(shù)排序解析,找到數(shù)組中數(shù)值最大的元素,創(chuàng)建一個長度為最大元素+1的臨時數(shù)組,這樣就可以把原始數(shù)組轉(zhuǎn)換為以原始數(shù)組元素值為下標(biāo),相同元素個數(shù)為值的臨時數(shù)組,需要的朋友可以參考下
    2023-10-10
  • IntelliJ IDEA將導(dǎo)入的項目轉(zhuǎn)成maven項目

    IntelliJ IDEA將導(dǎo)入的項目轉(zhuǎn)成maven項目

    這篇文章主要介紹了IntelliJ IDEA將導(dǎo)入的項目轉(zhuǎn)成maven項目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot3 整合Docker-Compose的實現(xiàn)步驟

    SpringBoot3 整合Docker-Compose的實現(xiàn)步驟

    本文主要介紹了SpringBoot3 整合Docker-Compose的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • 詳解spring cloud如何使用spring-test進(jìn)行單元測試

    詳解spring cloud如何使用spring-test進(jìn)行單元測試

    這篇文章主要介紹了spring cloud如何使用spring-test進(jìn)行單元測試,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java多線程事務(wù)回滾@Transactional失效處理方案

    Java多線程事務(wù)回滾@Transactional失效處理方案

    這篇文章主要介紹了Java多線程事務(wù)回滾@Transactional失效處理方案,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • Java裝飾器設(shè)計模式_動力節(jié)點(diǎn)Java學(xué)院整理

    Java裝飾器設(shè)計模式_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java裝飾器設(shè)計模式的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-05-05
  • Prometheus監(jiān)控Springboot程序的實現(xiàn)方法

    Prometheus監(jiān)控Springboot程序的實現(xiàn)方法

    這篇文章主要介紹了Prometheus監(jiān)控Springboot程序的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

    SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

    這篇文章主要介紹了SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • 利用idea搭建SSM項目看這一篇就夠了

    利用idea搭建SSM項目看這一篇就夠了

    SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis兩個開源框架整合而成(SpringMVC是Spring中的部分內(nèi)容),常作為數(shù)據(jù)源較簡單的web項目的框架,下面這篇文章主要給大家介紹了關(guān)于利用idea搭建SSM項目的相關(guān)資料,需要的朋友可以參考下
    2023-05-05

最新評論

武邑县| 峡江县| 瓦房店市| 玉田县| 双桥区| 运城市| 孝义市| 宁陵县| 洛扎县| 汝州市| 晴隆县| 闻喜县| 沙洋县| 会理县| 安塞县| 和硕县| 宜兴市| 确山县| 宝丰县| 阳西县| 英吉沙县| 兰考县| 望奎县| 海林市| 高要市| 韶山市| 阳山县| 武夷山市| 连江县| 辉南县| 西安市| 巴塘县| 海阳市| 叙永县| 浙江省| 简阳市| 衡南县| 馆陶县| 绥化市| 南岸区| 八宿县|