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

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

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

分析

總體分析

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

簡單介紹下springsecuriy用到的rediskey

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

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

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

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

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

方案

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

定時任務(wù)處理

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

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

yml中配置

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

cookie過多治理

總體方案

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

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

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

這里簡單介紹下springsecurity的攔截器加載順序

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

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

生成自定義session處理攔截器

創(chuàng)建一個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
     * 這里這樣注入,避免被掃包時加入到fitlers中,然后手動加入攔截器,設(shè)置在UsernamePasswordAuthenticationFilter之前執(zhí)行
     * 注意JwtAuthenticationTokenFilter 不能加注解,加的話,jwt會工作兩次
     */
    @Bean("jwtAuthenticationTokenFilter")
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

    /**
     * 配置資源服務(wù)器請求相關(guān)
     *
     * @param http 請求
     * @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()//允許所有訪問,權(quán)限控制交由filter
                .anyRequest().authenticated()
        ;
        http.addFilterBefore(mySessionRepositoryFilter, SessionManagementFilter.class);
    }



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

以上就是SpringSecurity導(dǎo)致Redis壓力大問題的解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringSecurity導(dǎo)致Redis壓力大的資料請關(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屬性值注入,綁定配置類和通過 environment獲取這三種方式,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2024-01-01
  • Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀

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

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

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

    分布式配置管理平臺是為了解決配置管理問題而出現(xiàn)的,它能夠?qū)崟r管理配置信息,確保配置的實(shí)時性和高可用性,配置管理平臺通?;谕扑?訂閱模式,客戶端訂閱配置信息,配置中心負(fù)責(zé)推送配置數(shù)據(jù),常見的分布式配置管理平臺包括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)目都會有這兩個文件,但是idea當(dāng)中應(yīng)該是沒有的,所以導(dǎo)入會出現(xiàn)兼容問題,但是本篇文章會教大家如何導(dǎo)入,并且導(dǎo)入過后還能使用tomcat運(yùn)行,需要的朋友可以參考下
    2023-08-08
  • Java基礎(chǔ)之代理原理與用法詳解

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

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

    ArrayList源碼和多線程安全問題分析

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

    Java中的RMI使用方法詳解

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

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

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

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

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

最新評論

依兰县| 贵南县| 玉树县| 仲巴县| 临桂县| 饶河县| 崇明县| 普兰县| 德阳市| 柘荣县| 黔江区| 泰顺县| 磐安县| 玉山县| 德州市| 桂林市| 丰都县| 安溪县| 福州市| 浦江县| 阿拉善左旗| 信丰县| 东海县| 南京市| 徐闻县| 宁德市| 郴州市| 普兰店市| 廊坊市| 邻水| 临澧县| 靖边县| 桃江县| 东海县| 台湾省| 新巴尔虎左旗| 鹿邑县| 镇康县| 呈贡县| 普定县| 虞城县|