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

SpringSecurity導(dǎo)致Redis壓力大問(wèn)題的解決方案

 更新時(shí)間:2025年06月23日 08:28:46   作者:OnlyLowG  
在我們現(xiàn)有的系統(tǒng)中,用于登錄的?Redis?服務(wù)器?CPU?占用率長(zhǎng)期處于?90%?的高位,這一狀況帶來(lái)了極大的風(fēng)險(xiǎn)隱患,因此,本文旨在解決這個(gè)問(wèn)題,下面小編給大家詳細(xì)介紹SpringSecurity導(dǎo)致Redis壓力大問(wèn)題的解決方案,需要的朋友可以參考下

分析

總體分析

經(jīng)過(guò)深入分析,我發(fā)現(xiàn) Redis 的 hgetall 操作極為頻繁,而這些操作主要是由 Spring Security 框架執(zhí)行,主要是hgetall 獲取spring:session:expirations:{timestamp}中的所有會(huì)話、一是hgetall獲取的數(shù)據(jù)量過(guò)大,二是執(zhí)行hgetall過(guò)于頻繁。

簡(jiǎn)單介紹下springsecuriy用到的rediskey

Redis Key說(shuō)明
spring:session:sessions:{sessionId}Spring Session 的默認(rèn)存儲(chǔ) Key,用于存儲(chǔ)每個(gè)會(huì)話的信息,其中 {sessionId} 是具體的會(huì)話 ID。
spring:session:sessions:expires:{sessionId}存儲(chǔ)會(huì)話的過(guò)期時(shí)間戳,與具體的會(huì)話 ID 相關(guān)聯(lián)。
spring:session:expirations:{timestamp}存儲(chǔ)每分鐘需要過(guò)期的會(huì)話 ID 集合,{timestamp} 是每分鐘的時(shí)間戳。
spring:session:index:org.springframework.session
.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:
索引 Key,用于存儲(chǔ)用戶名與會(huì)話 ID 的映射關(guān)系,方便根據(jù)用戶名快速查找對(duì)應(yīng)的會(huì)話 ID 集合。

抽絲剝繭,命中難點(diǎn)

進(jìn)一步調(diào)查發(fā)現(xiàn),我們的系統(tǒng)目前存在兩套鑒權(quán)體系,一套基于 token,另一套基于 cookie。雖然 token 鑒權(quán)體系本身并未直接使用 Redis,但由于集成了 Spring Security 框架,token 類型同樣會(huì)生成 cookie,并由此對(duì) Redis 進(jìn)行讀寫操作。

在實(shí)際使用中,采用 cookie 鑒權(quán)方式的主要是管理系統(tǒng),其使用人員相對(duì)較少;而 token 鑒權(quán)方式的使用量卻極為龐大,是導(dǎo)致 Redis CPU 占用率居高不下的關(guān)鍵因素。此外,我們所有應(yīng)用都默認(rèn)開(kāi)啟了 “Spring 定時(shí)清理過(guò)期會(huì)話” 的任務(wù),這一任務(wù)也導(dǎo)致了 QPS(每秒查詢率)過(guò)高,進(jìn)一步加劇了 Redis 的負(fù)載。

springsecurity定時(shí)清理會(huì)話任務(wù),如果不配置,默認(rèn)是每分鐘執(zhí)行一次

方案

分析出結(jié)果后,解決方案也呼之欲出了

定時(shí)任務(wù)處理

僅在少數(shù)特定的應(yīng)用中保留 session 過(guò)期處理機(jī)制。

如果是springboot2及以上,則可以通過(guò)配置關(guān)掉。而我們用的springboot1,配置無(wú)法關(guān)掉,只能另辟蹊徑,把非登錄相關(guān)應(yīng)用的清理時(shí)間都改為一天一次或一月一次。修改方式如下

yml中配置

spring:
  session:
    cleanup:
      cron:
        # spring session 定期清理redis關(guān)閉,這個(gè)定時(shí)任務(wù)用戶中心開(kāi)啟即可
        # expression: '-' springboot2.0才支持
        expression: '0 02 02 ? * *'

cookie過(guò)多治理

總體方案

對(duì)于采用 token 鑒權(quán)方式的系統(tǒng),不再生成 cookie,避免對(duì) Redis 進(jìn)行讀寫操作。

因?yàn)閟pringsecurity默認(rèn)使用spring-session中的 SessionRepositoryFilter來(lái)進(jìn)行session的操作,所以我們需要生成一個(gè)自定義session處理攔截器,來(lái)覆蓋springsecurity自身的處理,如果header中存在token,就不再執(zhí)行SessionRepositoryFilter攔截器。就不會(huì)對(duì)redis進(jìn)行任何操作。

我們需要添加攔截器,需要他在SessionManagementFilter攔截器執(zhí)行前執(zhí)行,然后重新打sso包,讓各應(yīng)用更新使用(SessionRepositoryFilter 并非 Spring Security 默認(rèn)過(guò)濾器鏈的一部分,它通常是通過(guò) spring-session 項(xiàng)目引入的,以便在分布式應(yīng)用中共享會(huì)話信息。在實(shí)際使用中,SessionRepositoryFilter 通常在 SessionManagementFilter 之前執(zhí)行,以便能夠正確地管理和存儲(chǔ)會(huì)話信息)

這里簡(jiǎn)單介紹下springsecurity的攔截器加載順序

序號(hào)過(guò)濾器名稱說(shuō)明
1SecurityContextPersistenceFilter恢復(fù)安全上下文,從會(huì)話或請(qǐng)求中加載安全信息,為后續(xù)過(guò)濾器的執(zhí)行奠定基礎(chǔ)。
2HeaderWriterFilter添加安全相關(guān)的 HTTP 響應(yīng)頭,如內(nèi)容安全策略(CSP)、HTTP 嚴(yán)格傳輸安全(HSTS)等,增強(qiáng)應(yīng)用的安全性。
3CorsFilter處理跨域資源共享(CORS)請(qǐng)求,驗(yàn)證跨域請(qǐng)求的合法性。
4CsrfFilter驗(yàn)證 CSRF 令牌,防止跨站請(qǐng)求偽造攻擊,保護(hù)應(yīng)用免受惡意請(qǐng)求的侵害。
5LogoutFilter處理注銷請(qǐng)求,使用戶能夠安全地退出應(yīng)用,清除相關(guān)的安全上下文。
6UsernamePasswordAuthenticationFilter處理基于用戶名和密碼的登錄請(qǐng)求,驗(yàn)證用戶的身份,并在驗(yàn)證成功后創(chuàng)建認(rèn)證對(duì)象。
7DefaultLoginPageGeneratingFilter如果未配置自定義登錄頁(yè),生成默認(rèn)的登錄頁(yè)面,簡(jiǎn)化了登錄流程的實(shí)現(xiàn)。
8BasicAuthenticationFilter處理 HTTP Basic 認(rèn)證,驗(yàn)證請(qǐng)求中的認(rèn)證信息,并在驗(yàn)證成功后創(chuàng)建認(rèn)證對(duì)象。
9BearerTokenAuthenticationFilter提取 JWT 等令牌進(jìn)行認(rèn)證,適用于基于令牌的認(rèn)證機(jī)制。
10RequestCacheAwareFilter恢復(fù)緩存的請(qǐng)求,以便在用戶登錄后能夠正確地重定向到原始請(qǐng)求的頁(yè)面。
11SecurityContextHolderFilter使安全上下文在請(qǐng)求中可用,為后續(xù)的安全操作提供上下文支持。
12AnonymousAuthenticationFilter如果未找到認(rèn)證信息,則分配一個(gè)匿名用戶認(rèn)證對(duì)象,使匿名用戶也能夠訪問(wèn)應(yīng)用中的某些資源。
13SessionManagementFilter處理會(huì)話固定防護(hù)和并發(fā)控制,管理會(huì)話相關(guān)的安全策略,如防止會(huì)話劫持等。
14ExceptionTranslationFilter捕獲安全異常并將其轉(zhuǎn)換為相應(yīng)的 HTTP 響應(yīng),如未認(rèn)證或未授權(quán)的錯(cuò)誤響應(yīng),使應(yīng)用能夠以合適的方式處理安全問(wèn)題。
15FilterSecurityInterceptor強(qiáng)制執(zhí)行授權(quán)規(guī)則,檢查用戶是否有權(quán)限訪問(wèn)請(qǐng)求的資源,是 Spring Security 授權(quán)過(guò)程的核心。

以下是為實(shí)現(xiàn)該解決方案所編寫的代碼:

生成自定義session處理攔截器

創(chuàng)建一個(gè)MySessionRepositoryFilter繼承SessionRepositoryFilter

package com.onlylowg.config.filter;

import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.session.SessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token filter
 */
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
@Component
public class MySessionRepositoryFilter extends SessionRepositoryFilter {


    private String tokenHeader = "Authorization";

    private String tokenHead = "bearer";

    private String accessToken = "access_token";

    /**
     * Creates a new instance.
     *
     * @param sessionRepository the <code>SessionRepository</code> to use. Cannot be null.
     */
    public MySessionRepositoryFilter(SessionRepository sessionRepository) {
        super(sessionRepository);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        if (!StringUtils.isNotBlank(request.getHeader(tokenHeader))) {

            super.doFilterInternal(request, response, filterChain);
            return;
        }
        filterChain.doFilter(request, response);

    }
}

配置攔截器

配置MySessionRepositoryFilter在SessionManagementFilter攔截器執(zhí)行前執(zhí)行

package com.onlylowg.config;


import com.onlylowg.config.filter.MySessionRepositoryFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.session.*;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

import javax.annotation.Resource;

/**
 * spring security配置類
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//    jwt:
//    header: Authorization
//    tokenHead: bearer
//    accessToken: access_token
    private String tokenHeader = "Authorization";

    private MySessionRepositoryFilter mySessionRepositoryFilter;

    private FindByIndexNameSessionRepository sessionRepository;

     * @date 2017-08-29
     * 這里這樣注入,避免被掃包時(shí)加入到fitlers中,然后手動(dòng)加入攔截器,設(shè)置在UsernamePasswordAuthenticationFilter之前執(zhí)行
     * 注意JwtAuthenticationTokenFilter 不能加注解,加的話,jwt會(huì)工作兩次
     */
    @Bean("jwtAuthenticationTokenFilter")
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

    /**
     * 配置資源服務(wù)器請(qǐng)求相關(guān)
     *
     * @param http 請(qǐng)求
     * @throws Exception 異常
     * @author WangHQ
     * @date 2017-07-13
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        init();

        http
                .csrf().disable()
                //.requestMatcher(new OAuthRequestedMatcher())
                .authorizeRequests()
                .antMatchers("/**").permitAll()//允許所有訪問(wèn),權(quán)限控制交由filter
                .anyRequest().authenticated()
        ;
        http.addFilterBefore(mySessionRepositoryFilter, SessionManagementFilter.class);
    }



    public void init() {
    
        mySessionRepositoryFilter = new MySessionRepositoryFilter(sessionRepository);
    }
}

以上就是SpringSecurity導(dǎo)致Redis壓力大問(wèn)題的解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringSecurity導(dǎo)致Redis壓力大的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳解

    Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳

    本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();
    2022-02-02
  • SpringBoot獲取配置信息的三種方式總結(jié)

    SpringBoot獲取配置信息的三種方式總結(jié)

    這篇文章給大家介紹了SpringBoot獲取配置信息的三種方式,@Value屬性值注入,綁定配置類和通過(guò) environment獲取這三種方式,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-01-01
  • Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀

    Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀

    這篇文章主要介紹了Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀,線程池是一種多線程處理形式,處理過(guò)程中將任務(wù)添加到隊(duì)列,然后在創(chuàng)建線程后自動(dòng)啟動(dòng)這些任務(wù),線程池線程都是后臺(tái)線程,需要的朋友可以參考下
    2023-12-12
  • 分布式下實(shí)現(xiàn)配置管理方式

    分布式下實(shí)現(xiàn)配置管理方式

    分布式配置管理平臺(tái)是為了解決配置管理問(wèn)題而出現(xiàn)的,它能夠?qū)崟r(shí)管理配置信息,確保配置的實(shí)時(shí)性和高可用性,配置管理平臺(tái)通?;谕扑?訂閱模式,客戶端訂閱配置信息,配置中心負(fù)責(zé)推送配置數(shù)據(jù),常見(jiàn)的分布式配置管理平臺(tái)包括Apollo、Diamond和Disconf
    2024-12-12
  • Intellij IDEA導(dǎo)入eclipse web項(xiàng)目的操作步驟詳解

    Intellij IDEA導(dǎo)入eclipse web項(xiàng)目的操作步驟詳解

    Eclipse當(dāng)中的web項(xiàng)目都會(huì)有這兩個(gè)文件,但是idea當(dāng)中應(yīng)該是沒(méi)有的,所以導(dǎo)入會(huì)出現(xiàn)兼容問(wèn)題,但是本篇文章會(huì)教大家如何導(dǎo)入,并且導(dǎo)入過(guò)后還能使用tomcat運(yùn)行,需要的朋友可以參考下
    2023-08-08
  • Java基礎(chǔ)之代理原理與用法詳解

    Java基礎(chǔ)之代理原理與用法詳解

    這篇文章主要介紹了Java基礎(chǔ)之代理原理與用法,結(jié)合實(shí)例形式詳細(xì)分析了java代理的概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-02-02
  • ArrayList源碼和多線程安全問(wèn)題分析

    ArrayList源碼和多線程安全問(wèn)題分析

    這篇文章主要介紹了ArrayList源碼和多線程安全問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面小編和大家一起來(lái)學(xué)習(xí)一下吧
    2019-05-05
  • Java中的RMI使用方法詳解

    Java中的RMI使用方法詳解

    這篇文章主要介紹了Java中的RMI使用方法,RMI是Java提供的一個(gè)完善的簡(jiǎn)單易用的遠(yuǎn)程方法調(diào)用框架,采用客戶服務(wù)器通信方式,在服務(wù)器上部署了提供各種服務(wù)的遠(yuǎn)程對(duì)象,下面我們來(lái)詳細(xì)講解
    2023-10-10
  • Spring框架中TaskExecutor類型Bean沖突導(dǎo)致的自動(dòng)注入失敗問(wèn)題的解決步驟

    Spring框架中TaskExecutor類型Bean沖突導(dǎo)致的自動(dòng)注入失敗問(wèn)題的解決步驟

    Spring中多個(gè)TaskExecutor Bean沖突導(dǎo)致注入失敗,本文給大家介紹的解決方案包括使用@Qualifier或@Primary明確注入目標(biāo)、重命名Bean、排除自動(dòng)配置,確保版本兼容以避免沖突,需要的朋友可以參考下
    2025-07-07
  • springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性詳解

    springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性詳解

    雪花算法在單節(jié)點(diǎn)下唯一,但在多副本Kubernetes環(huán)境中可能重復(fù),通過(guò)修改Pod名稱生成workId,解決了這個(gè)問(wèn)題,同時(shí)避免了第三方組件和網(wǎng)絡(luò)請(qǐng)求,本文給大家介紹springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性,感興趣的朋友一起看看吧
    2024-12-12

最新評(píng)論

麟游县| 南京市| 砚山县| 揭西县| 普兰县| 衡水市| 岱山县| 江北区| 富蕴县| 怀来县| 清流县| 平武县| 蓬溪县| 邵东县| 社旗县| 剑河县| 延川县| 靖宇县| 绥化市| 大安市| 宽甸| 尼勒克县| 巴楚县| 武山县| 图片| 波密县| 色达县| 康定县| 当涂县| 成安县| 天祝| 丰镇市| 天全县| 启东市| 临夏市| 河池市| 桐梓县| 奉化市| 麻江县| 大庆市| 澄迈县|