gateway网关获取分布式session的解决方法

<html> <head></head> <body> <div class="content ql-editor"> <p>首先我们需要解决spring-session-data-redis的序列化问题,spring-session-data-redis默认使用的是java对象序列化,需要Java对象实现Serializable而且在gateway中取出是乱码的. 所以我们要配置session配置类(<strong style="font-family: inherit; font-size: inherit;font-style;font-variant-ligatures;font-variant-caps;">类是配置在用户模块不是网关模块</strong>)</p> <div class="ql-code-block-container"> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-meta">@Configuration</span> </div> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">SessionConfig</span> { </div> <div class="ql-code-block"> &nbsp;​ </div> <div class="ql-code-block"> &nbsp; <span class="ql-token hljs-meta">@Bean</span> </div> <div class="ql-code-block"> &nbsp; <span class="ql-token hljs-keyword">public</span> CookieSerializer <span class="ql-token hljs-title">cookieSerializer()</span> { </div> <div class="ql-code-block"> &nbsp; &nbsp; <span class="ql-token hljs-type">DefaultCookieSerializer</span> <span class="ql-token hljs-variable">serializer</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">DefaultCookieSerializer</span>(); </div> <div class="ql-code-block"> &nbsp; &nbsp; <span class="ql-token hljs-keyword">return</span> serializer; </div> <div class="ql-code-block"> &nbsp; } </div> <div class="ql-code-block"> &nbsp;​ </div> <div class="ql-code-block"> &nbsp; <span class="ql-token hljs-meta">@Bean</span> </div> <div class="ql-code-block"> &nbsp; <span class="ql-token hljs-keyword">public</span> RedisSerializer&lt;Object&gt; <span class="ql-token hljs-title">springSessionDefaultRedisSerializer()</span> { </div> <div class="ql-code-block"> &nbsp; &nbsp; <span class="ql-token hljs-keyword">return</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">GenericJackson2JsonRedisSerializer</span>(); </div> <div class="ql-code-block"> &nbsp; } </div> <div class="ql-code-block"> &nbsp;​ </div> <div class="ql-code-block"> &nbsp;} </div> </div> <p><br></p> <p>gateway中也要记得引入依赖(spring-session-data-redis貌似可以不引入)</p> <div class="ql-code-block-container"> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; <span class="ql-token hljs-tag">&lt;dependency&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;groupId&gt;</span>org.springframework.boot<span class="ql-token hljs-tag">&lt;/groupId&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;artifactId&gt;</span>spring-boot-starter-data-redis<span class="ql-token hljs-tag">&lt;/artifactId&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;/dependency&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;dependency&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;groupId&gt;</span>org.springframework.session<span class="ql-token hljs-tag">&lt;/groupId&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;artifactId&gt;</span>spring-session-data-redis<span class="ql-token hljs-tag">&lt;/artifactId&gt;</span> </div> <div class="ql-code-block"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="ql-token hljs-tag">&lt;/dependency&gt;</span> </div> </div> <p><br></p> <p>在用户模块我们操作分布式session都是通过HttpServletRequest直接存取即可但在gateway中我们无法使用HttpServletRequest所以我们只能直接从redis中取首先我们要获取sessionid</p> <div class="ql-code-block-container"> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">cookieValue</span> <span class="ql-token hljs-operator">=</span> exchange.getRequest().getCookies().getFirst(WEB_SESSION_KEY).getValue(); </div> </div> <p>这里有一个坑,cookies中存的sessionid和reids中的格式不同要把sessionid转为base64</p> <div class="ql-code-block-container"> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">sessionId</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">String</span>(Base64.getDecoder().decode(cookieValue)); </div> </div> <p>现在就可以取出redis中的session了我我用RedisTemplate出现了报错使用这里使用了stringRedisTemplate,最后反序列化redis取出的值</p> <div class="ql-code-block-container"> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">sessionKey</span> <span class="ql-token hljs-operator">=</span>REDIS_SESSION_KEY + sessionId; </div> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-comment">// sessionAttr:userLoginState是我这里的写法 具体值取决于你存入的值的名称规则就是sessionAttr:[request.getSession().setAttribute()时指定的名称字段]</span> </div> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">session</span> <span class="ql-token hljs-operator">=</span>(String)stringRedisTemplate.opsForHash().get(sessionKey,<span class="ql-token hljs-string">"sessionAttr:userLoginState"</span>); </div> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">Gson</span> <span class="ql-token hljs-variable">gson</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">Gson</span>(); </div> <div class="ql-code-block"> &nbsp;<span class="ql-token hljs-type">User</span> <span class="ql-token hljs-variable">user</span> <span class="ql-token hljs-operator">=</span> gson.fromJson(session, User.class); </div> </div> <p></p> <p><span style="background-color: rgb(255, 255, 255); color: rgb(51, 51, 51);">gateway完整代码如下:</span></p> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> com.alibaba.nacos.shaded.com.google.gson.Gson; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> com.seig.teabackend.common.model.entity.User; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> lombok.extern.slf4j.Slf4j; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilterChain; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.cloud.gateway.filter.GlobalFilter; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.core.Ordered; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.data.redis.core.StringRedisTemplate; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.http.server.reactive.ServerHttpRequest; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.http.server.reactive.ServerHttpResponse; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.stereotype.Component; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> org.springframework.web.server.ServerWebExchange; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> reactor.core.publisher.Mono; </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> javax.annotation.Resource; </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">import</span> java.util.Base64; </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"><span class="ql-token hljs-meta">@Slf4j</span> </div> <div class="ql-code-block"><span class="ql-token hljs-meta">@Component</span> </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">CustomGlobalFilter</span> <span class="ql-token hljs-keyword">implements</span> <span class="ql-token hljs-title">GlobalFilter</span>, Ordered { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-keyword">static</span> <span class="ql-token hljs-keyword">final</span> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">WEB_SESSION_KEY</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-string">"SESSION"</span>; </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-keyword">static</span> <span class="ql-token hljs-keyword">final</span> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">REDIS_SESSION_KEY</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-string">"spring:session:sessions:"</span>; </div> <div class="ql-code-block"> <span class="ql-token hljs-meta">@Resource</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> StringRedisTemplate stringRedisTemplate; </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-meta">@Override</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> Mono&lt;Void&gt; <span class="ql-token hljs-title">filter(ServerWebExchange exchange, GatewayFilterChain chain)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-type">ServerHttpResponse</span> <span class="ql-token hljs-variable">response</span> <span class="ql-token hljs-operator">=</span> exchange.getResponse(); </div> <div class="ql-code-block"> <span class="ql-token hljs-type">ServerHttpRequest</span> <span class="ql-token hljs-variable">request</span> <span class="ql-token hljs-operator">=</span> exchange.getRequest(); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 1. 请求日志</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">requestPath</span> <span class="ql-token hljs-operator">=</span> request.getPath().value(); </div> <div class="ql-code-block"> requestPath = requestPath.replaceFirst(<span class="ql-token hljs-string">"/api/core"</span>, <span class="ql-token hljs-string">""</span>); </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">method</span> <span class="ql-token hljs-operator">=</span> request.getMethod().toString().toLowerCase(); </div> <div class="ql-code-block"> log.info(<span class="ql-token hljs-string">"请求唯一标识:"</span> + request.getId()); </div> <div class="ql-code-block"> log.info(<span class="ql-token hljs-string">"请求路径:"</span> + requestPath); </div> <div class="ql-code-block"> log.info(<span class="ql-token hljs-string">"请求方法:"</span> + method); </div> <div class="ql-code-block"> log.info(<span class="ql-token hljs-string">"请求参数:"</span> + request.getQueryParams()); </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">sourceAddress</span> <span class="ql-token hljs-operator">=</span> request.getLocalAddress().getHostString(); </div> <div class="ql-code-block"> log.info(<span class="ql-token hljs-string">"请求来源地址:"</span> + sourceAddress); </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 获取 Session</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">User</span> <span class="ql-token hljs-variable">user</span> <span class="ql-token hljs-operator">=</span> getSession(exchange); </div> <div class="ql-code-block"><span class="ql-token hljs-comment">// gson.fromJson()</span> </div> <div class="ql-code-block"> log.info(String.valueOf(user)); </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> chain.filter(exchange); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> User <span class="ql-token hljs-title">getSession(ServerWebExchange exchange)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">cookieValue</span> <span class="ql-token hljs-operator">=</span> exchange.getRequest().getCookies().getFirst(WEB_SESSION_KEY).getValue(); </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">sessionId</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">String</span>(Base64.getDecoder().decode(cookieValue)); </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">sessionKey</span> <span class="ql-token hljs-operator">=</span> REDIS_SESSION_KEY + sessionId; </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">session</span> <span class="ql-token hljs-operator">=</span> (String) stringRedisTemplate.opsForHash().get(sessionKey, <span class="ql-token hljs-string">"sessionAttr:userLoginState"</span>); </div> <div class="ql-code-block"> <span class="ql-token hljs-type">Gson</span> <span class="ql-token hljs-variable">gson</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">Gson</span>(); </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> gson.fromJson(session, User.class); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-meta">@Override</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-type">int</span> <span class="ql-token hljs-title">getOrder()</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> <span class="ql-token hljs-number">0</span>; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><br></p> </div> </body> </html>

下载 APP