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

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)開啟了 “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ù)用戶中心開啟即可
        # 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的equals和==的比較示例

    java的equals和==的比較示例

    這篇文章主要介紹了java的equals和==的比較示例,需要的朋友可以參考下
    2014-04-04
  • 如何給HttpServletRequest增加消息頭

    如何給HttpServletRequest增加消息頭

    這篇文章主要介紹了如何給HttpServletRequest增加消息頭的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Maven deploy plugin使用方式

    Maven deploy plugin使用方式

    這篇文章主要介紹了Maven deploy plugin使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • MyBatis快速入門

    MyBatis快速入門

    MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射的優(yōu)秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數(shù)的手工設(shè)置以及結(jié)果集的檢索。想要學(xué)好它,那就要從MyBatis基礎(chǔ)知識(shí)學(xué)起,下面跟著小編一起來(lái)看下吧
    2017-03-03
  • Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具

    Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • 使用Spring Boot Mybatis 搞反向工程的步驟

    使用Spring Boot Mybatis 搞反向工程的步驟

    這篇文章主要介紹了使用Spring Boot Mybatis 搞反向工程的步驟,幫助大家更好的理解和使用spring boot框架,感興趣的朋友可以了解下
    2021-01-01
  • SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)

    SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)

    在我們?nèi)粘5拈_發(fā)中,很多時(shí)候,定時(shí)任務(wù)都不是寫死的,而是寫到數(shù)據(jù)庫(kù)中,從而實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)配置,下面這篇文章主要給大家介紹了關(guān)于SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 解決druid監(jiān)控頁(yè)面SQL不顯示的問(wèn)題

    解決druid監(jiān)控頁(yè)面SQL不顯示的問(wèn)題

    這篇文章主要介紹了解決druid監(jiān)控頁(yè)面SQL不顯示的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot2零基礎(chǔ)到精通之配置文件與web開發(fā)

    SpringBoot2零基礎(chǔ)到精通之配置文件與web開發(fā)

    SpringBoot是一種整合Spring技術(shù)棧的方式(或者說(shuō)是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學(xué)習(xí)配置文件以及web相關(guān)的開發(fā)
    2022-03-03
  • java中的匿名內(nèi)部類詳細(xì)總結(jié)

    java中的匿名內(nèi)部類詳細(xì)總結(jié)

    以下是對(duì)java中的匿名內(nèi)部類進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-10-10

最新評(píng)論