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

Spring Security異步無法獲取用戶認(rèn)證信息的解決方法

 更新時(shí)間:2024年09月14日 09:31:13   作者:憶昔年.  
最近使用 Springboot 中 @Async 注解異步調(diào)用方法時(shí),發(fā)現(xiàn)無法獲取到用戶認(rèn)證信息,本文小編給大家介紹了Spring Security異步無法獲取用戶認(rèn)證信息的原因和解決方法,并通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下

原因:

Spring Security中的上下文SecurityContext的管理策略有三種

public class SecurityContextHolder {
    public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";

    public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";

    public static final String MODE_GLOBAL = "MODE_GLOBAL";
}

默認(rèn)的管理策略是:MODE_THREADLOCAL,對(duì)應(yīng)的策略類是
org.springframework.security.core.context.ThreadLocalSecurityContextHolderStrategy

以下是 Spring Security 初始化策略的代碼:

public class SecurityContextHolder {
    public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";

    public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";

    public static final String MODE_GLOBAL = "MODE_GLOBAL";
    // 獲取系統(tǒng)配置的策略
    private static String strategyName = System.getProperty(SYSTEM_PROPERTY);
    // 預(yù)初始化策略
    private static SecurityContextHolderStrategy strategy;
    
    private static void initializeStrategy() {
        if (MODE_PRE_INITIALIZED.equals(strategyName)) {
            Assert.state(strategy != null, "When using " + MODE_PRE_INITIALIZED
                    + ", setContextHolderStrategy must be called with the fully constructed strategy");
            return;
        }
        if (!StringUtils.hasText(strategyName)) {
            // Set default
            strategyName = MODE_THREADLOCAL;
        }
        if (strategyName.equals(MODE_THREADLOCAL)) {
            strategy = new ThreadLocalSecurityContextHolderStrategy();
            return;
        }
        if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
            strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
            return;
        }
        if (strategyName.equals(MODE_GLOBAL)) {
            strategy = new GlobalSecurityContextHolderStrategy();
            return;
        }
        // Try to load a custom strategy
        try {
            Class<?> clazz = Class.forName(strategyName);
            Constructor<?> customStrategy = clazz.getConstructor();
            strategy = (SecurityContextHolderStrategy) customStrategy.newInstance();
        }
        catch (Exception ex) {
            ReflectionUtils.handleReflectionException(ex);
        }
    }
}

ThreadLocalSecurityContextHolderStrategy 里保存Context的方式是 ThreadLocal,ThreadLocal 子線程并不能獲取父類線程的 ThreadLocalMap,
所以就導(dǎo)致了異步無法獲取到用戶認(rèn)證信息。

final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {

    private static final ThreadLocal<Supplier<SecurityContext>> contextHolder = new ThreadLocal<>();

}

解決方法:

更改上下文的管理策略 SecurityContextHolderStrategy 為 MODE_INHERITABLETHREADLOCAL,即

InheritableThreadLocalSecurityContextHolderStrategy,里面保存上下文的方式是 InheritableThreadLocal,可以獲取父線程的 ThreadLocalMap。

final class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {

	private static final ThreadLocal<Supplier<SecurityContext>> contextHolder = new InheritableThreadLocal<>();

}

InheritableThreadLocal可以獲取到子線程信息‌,主要是因?yàn)樗荰hreadLocal的一個(gè)子類,設(shè)計(jì)用來在父子線程間傳遞數(shù)據(jù)。
ThreadLocal變量通常只在當(dāng)前線程中存在,并且每個(gè)線程都有其自己的ThreadLocalMap,
這樣保證了線程間的數(shù)據(jù)隔離。然而,在某些情況下,我們需要父線程中的數(shù)據(jù)能夠在由父線程創(chuàng)建的子線程中被訪問,
這時(shí)就需要使用InheritableThreadLocal。
InheritableThreadLocal的實(shí)現(xiàn)機(jī)制使其能夠在子線程中訪問父線程的數(shù)據(jù)。具體來說,當(dāng)父線程創(chuàng)建一個(gè)子線程時(shí),
InheritableThreadLocal會(huì)采取措施確保子線程可以訪問到父線程中設(shè)置的InheritableThreadLocal變量。
這通常涉及到在子線程的Thread對(duì)象中復(fù)制父線程的ThreadLocalMap,從而使子線程能夠訪問到父線程中設(shè)置的變量。
這種機(jī)制允許在多線程環(huán)境中,特別是在使用線程池等場(chǎng)景下,實(shí)現(xiàn)父子線程間數(shù)據(jù)的傳遞和共享。
需要注意的是,雖然InheritableThreadLocal提供了在子線程中訪問父線程數(shù)據(jù)的能力,但它并不適用于所有情況,
特別是在復(fù)雜的線程交互中可能需要更精細(xì)的控制。此外,使用InheritableThreadLocal時(shí)也需要注意避免內(nèi)存泄漏等問題,因?yàn)槿绻划?dāng)使用,
它可能會(huì)導(dǎo)致資源的不當(dāng)占用‌。

代碼:

  • 1、可以在配置 Security 的配置類中添加 Bean
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
        factoryBean.setTargetClass(SecurityContextHolder.class);
        factoryBean.setTargetMethod("setStrategyName");
        factoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
        return factoryBean;
    }
}
  • 2、可以在配置 Security 的配置類中添加類初始化方式,會(huì)在注入 SecurityContextHolder 之后調(diào)用其中靜態(tài)方法更改 SecurityContextHolderStrategy 的實(shí)現(xiàn)類
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @PostContruct
    public void init() {
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }
}
  • 3、可以在啟動(dòng)項(xiàng)加上 -Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL 參數(shù),啟動(dòng)時(shí)更改 SecurityContextHolderStrategy 的實(shí)現(xiàn)類

以上就是Spring Security異步無法獲取用戶認(rèn)證信息的解決方法的詳細(xì)內(nèi)容,更多關(guān)于Spring Security異步無法獲取信息的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在SpringBoot中使用MongoDB的簡(jiǎn)單場(chǎng)景案例

    在SpringBoot中使用MongoDB的簡(jiǎn)單場(chǎng)景案例

    MongoDB 是一種非關(guān)系型數(shù)據(jù)庫(kù),也被稱為 NoSQL 數(shù)據(jù)庫(kù),它主要以文檔的形式存儲(chǔ)數(shù)據(jù),本文給大家介紹了在SpringBoot中使用MongoDB的簡(jiǎn)單場(chǎng)景案例,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • MybatisPlus公共字段自動(dòng)注入方法實(shí)現(xiàn)

    MybatisPlus公共字段自動(dòng)注入方法實(shí)現(xiàn)

    本文介紹了MybatisPlus公共字段自動(dòng)注入方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • 實(shí)現(xiàn) Java 本地緩存的方法解析

    實(shí)現(xiàn) Java 本地緩存的方法解析

    這篇文章主要介紹了實(shí)現(xiàn) Java 本地緩存的方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 使用Spring?Boot進(jìn)行單元測(cè)試詳情

    使用Spring?Boot進(jìn)行單元測(cè)試詳情

    這篇文章主要介紹了使用Spring?Boot進(jìn)行單元測(cè)試詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • Java多線程之同步工具類Exchanger

    Java多線程之同步工具類Exchanger

    這篇文章主要介紹了Java多線程之同步工具類Exchanger,Exchanger 是一個(gè)用于線程間協(xié)作的工具類,Exchanger用于進(jìn)行線程間的數(shù)據(jù)交換,它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn),兩個(gè)線程可以交換彼此的數(shù)據(jù),下面來看看具體內(nèi)容吧
    2021-10-10
  • Java命令行下Jar包打包小結(jié)

    Java命令行下Jar包打包小結(jié)

    這篇文章主要介紹了Java命令行下Jar包打包小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • MyBatis中實(shí)現(xiàn)數(shù)據(jù)封裝的示例代碼

    MyBatis中實(shí)現(xiàn)數(shù)據(jù)封裝的示例代碼

    本文主要介紹了MyBatis中實(shí)現(xiàn)數(shù)據(jù)封裝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-09-09
  • java對(duì)同一個(gè)文件進(jìn)行讀寫操作方法

    java對(duì)同一個(gè)文件進(jìn)行讀寫操作方法

    在本篇文章里我們給大家詳細(xì)講述了java對(duì)同一個(gè)文件進(jìn)行讀寫操作的方法和知識(shí)點(diǎn),需要的朋友們可以參考學(xué)習(xí)下。
    2018-10-10
  • Spring?Bean創(chuàng)建的另一條捷徑

    Spring?Bean創(chuàng)建的另一條捷徑

    這篇文章主要為大家介紹了Spring?Bean創(chuàng)建的另一條方法捷徑詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java代碼審計(jì)之URL重定向的問題解決

    Java代碼審計(jì)之URL重定向的問題解決

    URLRedirect url重定向漏洞也稱url任意跳轉(zhuǎn)漏洞,網(wǎng)站信任了用戶的輸入導(dǎo)致惡意攻擊,本文主要介紹了Java代碼審計(jì)之URL重定向的問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06

最新評(píng)論

明星| 富平县| 轮台县| 内乡县| 称多县| 新乡县| 永川市| 吴旗县| 都安| 吴忠市| 眉山市| 阜宁县| 上杭县| 乌苏市| 维西| 沁阳市| 昭苏县| 云浮市| 安阳市| 天祝| 博爱县| 津南区| 洞口县| 霍州市| 清新县| 临沭县| 左贡县| 项城市| 梅河口市| 克什克腾旗| 进贤县| 勃利县| 东安县| 花莲县| 陆良县| 香港| 衡阳市| 墨竹工卡县| 上犹县| 巴楚县| 平谷区|