欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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)文章

  • Java實現(xiàn)文件分片上傳接口的示例代碼

    Java實現(xiàn)文件分片上傳接口的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實現(xiàn)文件分片上傳的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2022-07-07
  • Spring入門到精通之Bean標(biāo)簽詳解

    Spring入門到精通之Bean標(biāo)簽詳解

    這篇文章主要為大家詳細(xì)介紹了Spring中Bean的標(biāo)簽,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Spring有一定的幫助,快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java實現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法示例

    Java實現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法示例

    這篇文章主要介紹了Java實現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法,涉及java針對數(shù)組的遍歷、判斷、輸出等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • Java后臺返回和處理JSon數(shù)據(jù)的方法步驟

    Java后臺返回和處理JSon數(shù)據(jù)的方法步驟

    這篇文章主要介紹了Java后臺返回和處理JSon數(shù)據(jù)的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java中重載與重寫的對比與區(qū)別

    Java中重載與重寫的對比與區(qū)別

    這篇文章主要介紹了Java中重載與重寫的對比與區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • 一文帶你了解gson如何序列化子類

    一文帶你了解gson如何序列化子類

    這篇文章主要為大家詳細(xì)介紹了gson如何序列化子類的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-10-10
  • 關(guān)于JFormDesigner的安裝及破姐超詳細(xì)教程

    關(guān)于JFormDesigner的安裝及破姐超詳細(xì)教程

    JFormDesigner是一種先進(jìn)的圖形用戶界面Swing?的設(shè)計工具(非開源),具有一個獨立的開發(fā)工具產(chǎn)品和基于不同開發(fā)工具如Eclipse、NetBeans等的開發(fā)插件,本文給大家介紹JFormDesigner安裝破解教程,感興趣的朋友一起看看吧
    2023-12-12
  • Spring Security動態(tài)權(quán)限的實現(xiàn)方法詳解

    Spring Security動態(tài)權(quán)限的實現(xiàn)方法詳解

    這篇文章主要和小伙伴們簡單介紹下 Spring Security 中的動態(tài)權(quán)限方案,以便于小伙伴們更好的理解 TienChin 項目中的權(quán)限方案,感興趣的可以了解一下
    2022-06-06
  • java后臺接受到圖片后保存方法

    java后臺接受到圖片后保存方法

    在本篇文章里小編給大家整理了關(guān)于java后臺接受到圖片后怎么保存的相關(guān)知識點,需要的朋友們參考學(xué)習(xí)下。
    2019-06-06
  • JavaWeb如何實現(xiàn)限制單個賬號多處登錄

    JavaWeb如何實現(xiàn)限制單個賬號多處登錄

    這篇文章主要介紹了JavaWeb如何實現(xiàn)限制單個賬號多處登錄問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論