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

Spring Security注冊過濾器注意事項(xiàng)詳解

 更新時(shí)間:2024年06月04日 08:22:33   作者:江南一點(diǎn)雨  
前兩天和小伙伴聊了 Spring Security+JWT 實(shí)現(xiàn)無狀態(tài)登錄,然后有小伙伴反饋了一個(gè)問題,感覺這是一個(gè)我們平時(shí)寫代碼容易忽略的問題,所以本文給大家介紹了Spring Security注冊過濾器注意事項(xiàng),需要的朋友可以參考下

一 問題復(fù)原

先來說問題吧,在 Spring Security+JWT 登錄中,整體上的思路就是用戶登錄成功之后返回 JWT 字符串,然后以后用戶每次請求都攜帶上 JWT 字符串,服務(wù)端進(jìn)行校驗(yàn),校驗(yàn)通過之后,請求繼續(xù)執(zhí)行。

按照上面的思路,我們的項(xiàng)目中需要有一個(gè) JwtFilter 用來從請求中提取請求傳來的 Jwt 字符串進(jìn)行校驗(yàn),類似下面這樣:

@Component
public class JwtFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        String requestURI = req.getRequestURI();
        if ("/login".equals(requestURI)) {
            //登錄請求,無需校驗(yàn)令牌,請求繼續(xù)執(zhí)行
            filterChain.doFilter(xxx,xxx);
            return;
        }
        //令牌校驗(yàn)
    }
}

然后有一個(gè)小伙伴反饋,在項(xiàng)目中使用了 WebSecurityCustomizer 給 Swagger 相關(guān)的請求都放行了,結(jié)果這些被放行的請求都被 JwtFilter 攔截了,這是咋回事呢?

首先小伙伴們要知道,使用 WebSecurityCustomizer 放行的請求,都不再經(jīng)過 SecurityFilter 了,所以按理不該再被 JwtFilter 攔截了,因?yàn)?JwtFilter 是隸屬于 SecurityFilter 這個(gè)過濾器鏈中的,并非原生的跟 Servlet 平級的那種 Filter。

但是為什么又?jǐn)r截了呢?

松哥看了下代碼,發(fā)現(xiàn)問題出在 @Component 這個(gè)注解上。

二 原理分析

在 Spring Boot 項(xiàng)目啟動的時(shí)候,有一個(gè)環(huán)節(jié)就是把 Spring 容器中所有類型為 Filter 的 Bean 找出來,并且自動添加到容器的過濾器鏈條中(注意不是添加到 Spring Security 過濾器鏈中)。

這段代碼的邏輯位于 ServletContextInitializerBeans#addAdaptableBeans 方法中,在該方法中,會調(diào)用 addAsRegistrationBean 方法完成以上事情:

private <T, B extends T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type,
		Class<B> beanType, RegistrationBeanAdapter<T> adapter) {
	List<Map.Entry<String, B>> entries = getOrderedBeansOfType(beanFactory, beanType, this.seen);
	for (Entry<String, B> entry : entries) {
		String beanName = entry.getKey();
		B bean = entry.getValue();
		if (this.seen.add(bean)) {
			// One that we haven't already seen
			RegistrationBean registration = adapter.createRegistrationBean(beanName, bean, entries.size());
			int order = getOrder(bean);
			registration.setOrder(order);
			this.initializers.add(type, registration);
		}
	}
}

可以看到,這里傳入的參數(shù) type 和 beanType 都是 Filter,從 Spring 容器中找到 Filter 類型的 Bean 存入到 initializers 集合中。不過注意,添加到集合中的實(shí)際上是封裝之后的 registration 對象,這個(gè)對象通過 adapter.createRegistrationBean 方法創(chuàng)建出來,在該方法中,由于我們沒有為當(dāng)前過濾器設(shè)置攔截的請求地址,所以默認(rèn)攔截所有請求,攔截規(guī)則是 /*。

最后在 ServletWebServerApplicationContext#selfInitialize 方法中遍歷上一步找到的過濾器,并逐個(gè)進(jìn)行配置,相關(guān)代碼如下:

DynamicRegistrationBean#register:

@Override
protected final void register(String description, ServletContext servletContext) {
    //注冊過濾器
	D registration = addRegistration(description, servletContext);
	//省略
}

AbstractFilterRegistrationBean#addRegistration:

@Override
protected Dynamic addRegistration(String description, ServletContext servletContext) {
	Filter filter = getFilter();
	return servletContext.addFilter(getOrDeduceName(filter), filter);
}

可以看到,這最終就是大家熟知的添加過濾器的代碼了。

三 解決方案

找到問題的原因,那么問題就好解決了。

問題的產(chǎn)生,主要是因?yàn)?Spring 自動查找容器中所有 Filter 類型的 Bean,并進(jìn)行配置,那么我們的解決方案就是不要把這個(gè) Bean 注冊到 Spring 容器中,即不要添加 @Component 注解,而是直接自己 new 出來就行了,在配置過濾器鏈的時(shí)候,像下面這樣配置即可:

http.addFilterAfter(new JwtFilter(redisTemplate), SecurityContextHolderFilter.class);

經(jīng)過上面這樣配置之后,JwtFilter 就不存在于原生過濾器鏈中了,只是單純的存在于 SecurityFilter 中。

理解了 Spring Security 原理,那么日常開發(fā)中各種奇奇怪怪的情況,我們就都能輕車熟路的解決了。

到此這篇關(guān)于Spring Security注冊過濾器注意事項(xiàng)詳解的文章就介紹到這了,更多相關(guān)Spring Security注冊過濾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring boot中mongodb的使用

    Spring boot中mongodb的使用

    MongoDB是最早熱門非關(guān)系數(shù)據(jù)庫的之一,使用也比較普遍,一般會用做離線數(shù)據(jù)分析來使用,放到內(nèi)網(wǎng)的居多。這篇文章主要介紹了Spring boot中mongodb的使用,需要的朋友可以參考下
    2017-05-05
  • Spring?Native打包本地鏡像的操作方法(無需通過Graal的maven插件buildtools)

    Spring?Native打包本地鏡像的操作方法(無需通過Graal的maven插件buildtools)

    這篇文章主要介紹了Spring?Native打包本地鏡像,無需通過Graal的maven插件buildtools,本文探索一下,如果不通過這個(gè)插件來生成鏡像,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • java自定義注解接口實(shí)現(xiàn)方案

    java自定義注解接口實(shí)現(xiàn)方案

    java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說明、配置的功能,本文將詳細(xì)介紹,此功能的實(shí)現(xiàn)方法
    2012-11-11
  • Spring如何通過注解存儲和讀取對象詳解

    Spring如何通過注解存儲和讀取對象詳解

    在Spring中,要想更簡單的存儲和讀取對象的核心是使用注解,這篇文章主要給大家介紹了關(guān)于Spring如何通過注解存儲和讀取對象的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Java Scanner輸入兩個(gè)數(shù)組的方法

    Java Scanner輸入兩個(gè)數(shù)組的方法

    今天小編就為大家分享一篇Java Scanner輸入兩個(gè)數(shù)組的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • 一次Jvm old過高的排查過程實(shí)戰(zhàn)記錄

    一次Jvm old過高的排查過程實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了一次Jvm old過高的排查過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法

    微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法

    本篇文章主要介紹了微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法,具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • 一文了解Java中record和lombok的使用對比

    一文了解Java中record和lombok的使用對比

    Java的 record 關(guān)鍵字是Java 14中引入的一個(gè)新的語義特性。Lombok 是一個(gè)Java庫,可以自動生成一些已知的模式為Java字節(jié)碼。本文我們將探討各種使用情況,包括java record 的一些限制。對于每個(gè)例子,我們將看到Lombok如何派上用場,并比較這兩種解決方案
    2022-07-07
  • JDK基于CAS實(shí)現(xiàn)原子類盤點(diǎn)解析

    JDK基于CAS實(shí)現(xiàn)原子類盤點(diǎn)解析

    這篇文章主要為大家介紹了JDK基于CAS實(shí)現(xiàn)原子類盤點(diǎn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • java中建立0-10m的消息(字符串)實(shí)現(xiàn)方法

    java中建立0-10m的消息(字符串)實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava中建立0-10m的消息(字符串)實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05

最新評論