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

SpringCloud開(kāi)啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)

 更新時(shí)間:2023年02月14日 10:17:08   作者:一枝花傲寒  
這篇文章主要介紹了SpringCloud開(kāi)啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

備注:以下所有的gateway均指SpringCloud Gateway

一、原架構(gòu)

前端<->gateway<->console后端

原來(lái)session是在console-access中維護(hù)的,當(dāng)中間有了一層gateway之后,gateway會(huì)認(rèn)為session變了,從而將session的cookie信息重置,導(dǎo)致無(wú)法在前端的后續(xù)請(qǐng)求無(wú)法將cookie帶上來(lái)

如下圖所示的spring-web的代碼中這個(gè)state會(huì)變成State.NEW而非State.STARTED

在這種情況下,部署的時(shí)候只有跳過(guò)gateway才能正常進(jìn)行

即按照如下方式才能進(jìn)行session的判斷

前端<->console后端

二、調(diào)整架構(gòu)以及相應(yīng)的代碼

整個(gè)業(yè)務(wù)處理和原來(lái)的沒(méi)有任何改變

將session的判斷控制挪到gateway當(dāng)中

首先將console后端中登錄以及后續(xù)業(yè)務(wù)當(dāng)中涉及到session處理的部分都刪除

然后開(kāi)始改造gateway

1、Redis和session的配置

gateway的pom.xml增加

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

因?yàn)樾枰蕾?lài)Redis了,所以啟動(dòng)類(lèi)當(dāng)中刪除RedisAutoConfiguration.class

Nacos或者配置文件增加redis配置

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.username=redis7
spring.redis.password=XXX
spring.redis.database=10
spring.redis.pool.max-active=100
spring.redis.pool.max-wait=500
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=10
spring.redis.timeout=1000

2、增加配置類(lèi)

/**
 * 指定saveMode為ALWAYS 功能和flushMode類(lèi)似
 *
 * @author fengwei
 * @since 2022/11/8
 */

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpCookie;
import org.springframework.session.SaveMode;
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.session.CookieWebSessionIdResolver;
import org.springframework.web.server.session.WebSessionIdResolver;

import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@EnableRedisWebSession(saveMode = SaveMode.ALWAYS, maxInactiveIntervalInSeconds = 1200)
@Configuration
@Slf4j
public class RedisSessionConfig {
    /**
     * @return
     * @reference https://docs.spring.io/spring-session/reference/guides/boot-webflux-custom-cookie.html
     */
    @Bean
    public WebSessionIdResolver webSessionIdResolver() {
        CustomWebSessionIdResolver customWebSessionIdResolver = new CustomWebSessionIdResolver();
        //以下四項(xiàng)配置主要用于跨域調(diào)用讓客戶(hù)端處理cookie信息;若同域調(diào)用,下面四行可刪除
        customWebSessionIdResolver.addCookieInitializer((builder) -> builder.httpOnly(true));
        customWebSessionIdResolver.addCookieInitializer((builder) -> builder.path("/"));
        customWebSessionIdResolver.addCookieInitializer((builder) -> builder.sameSite("None"));
        customWebSessionIdResolver.addCookieInitializer((builder) -> builder.secure(true));
        return customWebSessionIdResolver;
    }

    private static class CustomWebSessionIdResolver extends CookieWebSessionIdResolver {
        // 重寫(xiě)resolve方法 對(duì)SESSION進(jìn)行base64解碼
        @Override
        public List<String> resolveSessionIds(ServerWebExchange exchange) {
            MultiValueMap<String, HttpCookie> cookieMap = exchange.getRequest().getCookies();
            // 獲取SESSION
            List<HttpCookie> cookies = cookieMap.get(getCookieName());
            if (cookies == null) {
                return Collections.emptyList();
            }
            return cookies.stream().map(HttpCookie::getValue).map(this::base64Decode).collect(Collectors.toList());
        }

        private String base64Decode(String base64Value) {
            try {
                byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
                String decodedCookieString = new String(decodedCookieBytes);
                log.debug("base64Value:{}, decodedCookieString:{} ", base64Value, decodedCookieString);
                return decodedCookieString;
            } catch (Exception ex) {
                //如果轉(zhuǎn)不了base64,就認(rèn)為原始值就是返回的
                log.debug("Unable to Base64 decode value:{} ", base64Value);
                return base64Value;
            }
        }
    }

}

3、應(yīng)答過(guò)濾器增加session設(shè)置

在ResponseLogFilter類(lèi)中增加

/*如果是控制臺(tái)登錄,則從里面取出securityRandom存在websession里面*/
if (request.getPath().toString().startsWith("/console/access/user/login")) {
    JSONObject jsonObject = JSONObject.parseObject(finalResponseBody);
    if ("0000".equals(jsonObject.getString("result"))) {
        JSONObject jsonObjectData = (JSONObject) jsonObject.get("data");
        String securityRandom = (String) jsonObjectData.get("securityrandom");
        exchange.getSession().subscribe(webSession -> {
            webSession.getAttributes().put("securityrandom", securityRandom);
        });
        try {
            //給200毫秒讓進(jìn)行session設(shè)置
            Thread.sleep(200);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

4、增加控制臺(tái)處理的過(guò)濾器ConsoleFilter

首選在配置文件或者Nacos增加配置項(xiàng)

#Y標(biāo)識(shí)需要檢查session;N表示不檢查session。開(kāi)發(fā)的時(shí)候可以配置為N
websession.ifcheck=Y

過(guò)濾器ConsoleFilter

import com.alibaba.cloud.commons.lang.StringUtils;
import com.jieyi.util.OrderedConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 控制臺(tái)登錄的過(guò)濾器,主要是拿用戶(hù)憑證的securityRandom
 *
 * @author fengwei
 * @date 2022-11-8
 */
@Component
@Slf4j
public class ConsoleFilter implements GlobalFilter, Ordered {
    private static final List<String> WHITE_LIST = Arrays.asList("/console/access/user/getOtp/V1", "/console/access/user/login/V1");

    @Value("${websession.ifcheck}")
    private String websessionIfcheck;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().toString();


        //不校驗(yàn)session就直接通過(guò)了
        if (!"Y".equals(websessionIfcheck)) {
            return chain.filter(exchange);
        }
        //在url白名單中放行
        boolean isWhiteUrl = WHITE_LIST.stream().anyMatch(path::endsWith);
        if (isWhiteUrl) {
            return chain.filter(exchange);
        }

        if (path.startsWith("/console")) {
            return exchange.getSession().flatMap(webSession -> {
                String securityrandomInSession = webSession.getAttribute("securityrandom");
                log.info("securityrandomInSession:{}", securityrandomInSession);
                if (StringUtils.isEmpty(securityrandomInSession)) {
                    byte[] bytes = "{\"status\":\"401\",\"msg\":\"Not login or login timeout\"}".getBytes(StandardCharsets.UTF_8);
                    DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return exchange.getResponse().writeWith(Flux.just(buffer));
                }
                return chain.filter(exchange);
            });

        } else {
            return chain.filter(exchange);
        }

    }

    @Override
    public int getOrder() {
        return OrderedConstant.LOGGING_FILTER;
    }
}

5、前端請(qǐng)求中增加(跨域時(shí))

withCredentials = true

只有增加這個(gè)請(qǐng)求才能攜帶和處理cookie

三、部署模式

1、同域

對(duì)于同域的部署http和https均可(當(dāng)然更建議https)

提供一個(gè)nginx同域部署的參考:

server {
  #console-samedomain-test
  listen 38093 ssl;
  proxy_set_header Host $host:38093;
  root html;
  index index.html index.htm;
  ssl_certificate      cert/server.crt;
  ssl_certificate_key  cert/server.key;
  ssl_session_timeout  5m;
  ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers  on;
  location / {
    proxy_pass http://127.0.0.1:30000/;
  }
  location /ccuconsole {
    proxy_pass http://127.0.0.1:5120/ccuconsole;
  }
}

該配置為https,走的38093端口

前端頁(yè)面訪(fǎng)問(wèn)https://ip:38093/ccuconsole

所有的請(qǐng)求都通過(guò)該同域的ip和端口轉(zhuǎn)發(fā)到http://127.0.0.1:30000對(duì)應(yīng)的服務(wù)(確保該服務(wù)中不存在/ccuconsole開(kāi)頭的路徑)中

2、跨域

對(duì)于跨域的部必須使用https(現(xiàn)在的瀏覽器版本的要求,瀏覽器已不再支持http的跨域了)

提供一個(gè)nginx跨域部署的參考:

server {
  #console-web-crossdomain-test
  listen 38091 ssl;
  proxy_set_header Host $host:38091;
  root html;
  index index.html index.htm;
  ssl_certificate      cert/server.crt;
  ssl_certificate_key  cert/server.key;
  ssl_session_timeout  5m;
  ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers  on;
  location /ccuconsole {
    proxy_pass http://127.0.0.1:5120/ccuconsole;
  }
}

server {
  #console-crossdomain-test
  listen 38092 ssl;
  proxy_set_header Host $host:38092;
  root html;
  index index.html index.htm;
  ssl_certificate      cert/server.crt;
  ssl_certificate_key  cert/server.key;
  ssl_session_timeout  5m;
  ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers  on;
  location / {
    proxy_pass http://127.0.0.1:30000/;
  }
}

前端頁(yè)面訪(fǎng)問(wèn)https://ip:38091/ccuconsole

所有的請(qǐng)求都通過(guò)該同域的ip和38092轉(zhuǎn)發(fā)到http://127.0.0.1:30000對(duì)應(yīng)的服務(wù)(確保該服務(wù)中有無(wú)/ccuconsole開(kāi)頭的路徑并不影響,但是為了可切換同域部署,不推薦存在/ccuconsole開(kāi)頭的路徑)中

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于SpringBoot項(xiàng)目遇到的坑--Date入?yún)?wèn)題

    基于SpringBoot項(xiàng)目遇到的坑--Date入?yún)?wèn)題

    這篇文章主要介紹了SpringBoot項(xiàng)目遇到的坑--Date入?yún)?wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Spring WebFlux的使用指南

    Spring WebFlux的使用指南

    這篇文章主要介紹了Spring WebFlux的使用指南,幫助大家更好的理解和學(xué)習(xí)使用Spring框架,感興趣的朋友可以了解下
    2021-05-05
  • Spring多種加載Bean方式解析

    Spring多種加載Bean方式解析

    本篇文章主要介紹了Spring多種加載Bean方式解析,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • JAVA jvm系列--java內(nèi)存區(qū)域

    JAVA jvm系列--java內(nèi)存區(qū)域

    下面小編就為大家?guī)?lái)一篇基于jvm java內(nèi)存區(qū)域的介紹。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-09-09
  • 解決Spring國(guó)際化文案占位符失效問(wèn)題的方法

    解決Spring國(guó)際化文案占位符失效問(wèn)題的方法

    本篇文章主要介紹了解決Spring國(guó)際化文案占位符失效問(wèn)題的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • 關(guān)于feign對(duì)x-www-form-urlencode類(lèi)型的encode和decode問(wèn)題

    關(guān)于feign對(duì)x-www-form-urlencode類(lèi)型的encode和decode問(wèn)題

    這篇文章主要介紹了關(guān)于feign對(duì)x-www-form-urlencode類(lèi)型的encode和decode問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • spring中的懶加載詳細(xì)解讀

    spring中的懶加載詳細(xì)解讀

    這篇文章主要介紹了spring中的懶加載詳細(xì)解讀,如果某個(gè)Bean再程序運(yùn)行周期中都可能不會(huì)被適用,那么可以設(shè)定該Bean為懶加載,優(yōu)勢(shì)是盡量節(jié)省了服務(wù)器的資源,缺點(diǎn)是可能會(huì)導(dǎo)致某個(gè)相應(yīng)的時(shí)間增加,需要的朋友可以參考下
    2023-10-10
  • MybatisPlus實(shí)現(xiàn)簡(jiǎn)單增刪改查功能

    MybatisPlus實(shí)現(xiàn)簡(jiǎn)單增刪改查功能

    這篇文章主要介紹了MybatisPlus實(shí)現(xiàn)簡(jiǎn)單增刪改查的相關(guān)資料,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • 解決Mac?m1?電腦?idea?卡頓的問(wèn)題

    解決Mac?m1?電腦?idea?卡頓的問(wèn)題

    這篇文章主要介紹了Mac?m1?電腦?idea?卡頓的問(wèn)題解決,文中給大家補(bǔ)充介紹了IDEA卡頓問(wèn)題處理方法,需要的朋友可以參考下
    2023-03-03
  • springboot時(shí)間格式化的五種方法總結(jié)(解決后端傳給前端的時(shí)間顯示不一致)

    springboot時(shí)間格式化的五種方法總結(jié)(解決后端傳給前端的時(shí)間顯示不一致)

    這篇文章主要給大家介紹了關(guān)于springboot時(shí)間格式化的五種方法,文中介紹的方法解決了后端傳給前端的時(shí)間顯示不一致,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01

最新評(píng)論

江油市| 舒城县| 万州区| 金坛市| 江油市| 贵阳市| 忻州市| 吐鲁番市| 仁布县| 嘉义县| 深泽县| 新巴尔虎左旗| 旅游| 青海省| 德江县| 阿拉善右旗| 兰溪市| 江津市| 报价| 华坪县| 罗田县| 宜兰县| 衡东县| 旅游| 富蕴县| 连州市| 陇西县| 肇州县| 雷州市| 贵阳市| 盐源县| 宜宾县| 马公市| 漳浦县| 富阳市| 兴仁县| 当阳市| 米脂县| 繁昌县| 威信县| 镶黄旗|