Gateway网关设置请求头乱码

news2024/9/27 15:17:56

问题描述:

​ 在做gateway用户认证过程中,我们将前端传过来的token字符串进行解析以后,将用户信息存入请求头往下传递的过程中,如果用户信息中存在中文,下游服务从请求头中获取到用户信息时会出现乱码

​ 总体来说,就是如果在gateway网关层设置了带有中文的请求头,在下游服务中获取会出现乱码

代码演示:

  1. SecurityFilterJwt.java

    private Mono<Void> dealJwt(String jwt, ServerWebExchange exchange, GatewayFilterChain chain, String headerKey) {
        try {
            // 获取token中的用户对象字符串
            String userJson = jwtUtils.checkJWT(jwt);
            // 将用户信息设置到请求头中
            ServerWebExchange serverWebExchange = setNewHeader(exchange, headerKey, userJson);
            return chain.filter(serverWebExchange);
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            return renderErrorMsg(exchange, ResponseStatusEnum.JWT_EXPIRE_ERROR);
        } catch (Exception e) {
            e.printStackTrace();
            return renderErrorMsg(exchange, ResponseStatusEnum.JWT_SIGNATURE_ERROR);
        }
    }
    
    public ServerWebExchange setNewHeader(ServerWebExchange exchange, String headerKey, String headerValue) {
        // 重新构建新的request
        ServerHttpRequest request = exchange.getRequest()
            .mutate()
            .header(headerKey, headerValue)
            .build();
        // 将新的request放入exchange中,通过断点调试,上面的request在设置进去时还是好的,问题应该是出现在下面代码
        return exchange.mutate()
            .request(request)
            .build();
    }
    
  2. JwtUserInterceptor.java

    package com.ajie.api.interceptor;
    
    import cn.hutool.core.net.URLDecoder;
    import com.ajie.api.context.UserContext;
    import com.ajie.common.constant.SecurityConstants;
    import com.ajie.common.utils.JsonUtils;
    import com.ajie.common.utils.StringUtils;
    import com.ajie.pojo.entity.Admin;
    import com.ajie.pojo.entity.Users;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.nio.charset.StandardCharsets;
    
    /**
     * @Description:
     * @Author: ajie
     */
    @Slf4j
    @Component
    public class JwtUserInterceptor implements HandlerInterceptor {
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 获取上游网关层设置的用户信息
            String appUserJson = request.getHeader(SecurityConstants.APP_USER_JSON);
            String saaSUserJson = request.getHeader(SecurityConstants.SAAS_USER_JSON);
            String adminUserJson = request.getHeader(SecurityConstants.ADMIN_USER_JSON);
    
            if (StringUtils.isNotBlank(appUserJson)) {
                log.warn("从请求头获取到的用户信息:{}", appUserJson);
                // 将用户信息设置到threadLocal中
                UserContext.setUsers(JsonUtils.toBean(appUserJson, Users.class));
            }
            if (StringUtils.isNotBlank(adminUserJson)) {
                adminUserJson = URLDecoder.decode(adminUserJson, StandardCharsets.UTF_8);
                UserContext.setAdmin(JsonUtils.toBean(adminUserJson, Admin.class));
            }
            return true;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 清理threadLocal,防止内存泄漏
            UserContext.clear();
        }
    }
    
  3. 启动微服务,调用相关接口

    image-20240805105737916

    从截图可以看到,下游服务在从请求头获取带有中文的信息时,出现了乱码

解决方案:

​ 可以在gateway设置新的请求头时进行URL编码,在下游获取请求头信息的时候,再通过URL解码。可以解决这个问题

代码演示:

  1. SecurityFilterJwt.java

    private Mono<Void> dealJwt(String jwt, ServerWebExchange exchange, GatewayFilterChain chain, String headerKey) {
        try {
            // 获取token中的用户对象字符串
            String userJson = jwtUtils.checkJWT(jwt);
            // 将用户信息设置到请求头中
            ServerWebExchange serverWebExchange = setNewHeader(exchange, headerKey, userJson);
            return chain.filter(serverWebExchange);
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            return renderErrorMsg(exchange, ResponseStatusEnum.JWT_EXPIRE_ERROR);
        } catch (Exception e) {
            e.printStackTrace();
            return renderErrorMsg(exchange, ResponseStatusEnum.JWT_SIGNATURE_ERROR);
        }
    }
    
    public ServerWebExchange setNewHeader(ServerWebExchange exchange, String headerKey, String headerValue) {
        // 重新构建新的request
        ServerHttpRequest request = exchange.getRequest()
            .mutate()
            // 重点:对请求头的值做URL编码,解决下游获取信息乱码的问题
            .header(headerKey, URLEncodeUtil.encode(headerValue,StandardCharsets.UTF_8))
            .build();
        // 将新的request放入exchange中,通过断点调试,上面的request在设置进去时还是好的,问题应该是出现在下面代码
        return exchange.mutate()
            .request(request)
            .build();
    }
    
  2. JwtUserInterceptor.java

    package com.ajie.api.interceptor;
    
    import cn.hutool.core.net.URLDecoder;
    import com.ajie.api.context.UserContext;
    import com.ajie.common.constant.SecurityConstants;
    import com.ajie.common.utils.JsonUtils;
    import com.ajie.common.utils.StringUtils;
    import com.ajie.pojo.entity.Admin;
    import com.ajie.pojo.entity.Users;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.nio.charset.StandardCharsets;
    
    /**
     * @Description:
     * @Author: ajie
     */
    @Slf4j
    @Component
    public class JwtUserInterceptor implements HandlerInterceptor {
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 获取上游网关层设置的用户信息
            String appUserJson = request.getHeader(SecurityConstants.APP_USER_JSON);
            String saaSUserJson = request.getHeader(SecurityConstants.SAAS_USER_JSON);
            String adminUserJson = request.getHeader(SecurityConstants.ADMIN_USER_JSON);
    
            if (StringUtils.isNotBlank(appUserJson)) {
                // 重点:对请求头中的值进行URL解码,解码gateway设置请求头乱码问题
                appUserJson = URLDecoder.decode(appUserJson, StandardCharsets.UTF_8);
                log.warn("从请求头获取到的用户信息:{}", appUserJson);
                // 将用户信息设置到threadLocal中
                UserContext.setUsers(JsonUtils.toBean(appUserJson, Users.class));
            }
            if (StringUtils.isNotBlank(adminUserJson)) {
                adminUserJson = URLDecoder.decode(adminUserJson, StandardCharsets.UTF_8);
                UserContext.setAdmin(JsonUtils.toBean(adminUserJson, Admin.class));
            }
            return true;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 清理threadLocal,防止内存泄漏
            UserContext.clear();
        }
    }
    
  3. 重新启动微服务,调用相关接口

    image-20240805110452046

    通过截图可以看到,乱码问题成功得到解决

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1981058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

担心异构数据库迁移踩“坑”?听听大咖们怎么说

在技术升级和国产化战略的双重推动下&#xff0c;如何将来自Oracle、MySQL等异构数据库的数据无缝迁移至国产数据库&#xff0c;已成为企业持续发展的关键一环。 YashanDB Meetup第13期特别邀请首届迁移体验官用户代表、TechTalk社区创始人尚雷&#xff0c;YashanDB 售后服务负…

【python】Scrapy中常见的“Response Not Ready”或“Response Not 200”错误分析及解决

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

家用洗地机有什么推荐的吗?洗地机口碑榜前四名推荐

随着日常清洁需求的提升&#xff0c;如今洗地机已成为现代家居清洁的好帮手&#xff0c;承担着家庭卫生的重要角色&#xff0c;而一台高效、便捷的洗地机更是成为了众多家庭清洁卫生必备工具。 不过市场上的洗地机品牌众多&#xff0c;每个品牌下又有诸多系列&#xff0c;让人…

动态规划之——背包DP(入门篇)

文章目录 概要说明01背包模板例题题意概要思路code1code2 01背包的应用题题目来源思路code 完全背包模板例题题意概要思路code 概要说明 本文只讲了01背包和完全背包&#xff0c;至于其他背包问题后续补充 01背包 模板例题 点击这里 题意概要 思路 01背包的模板题 首先对…

SAM 图像分割算法计算物体表面积

参考: https://enpeicv.com/forum.php?mod=viewthread&tid=90&extra=page%3D1 使用SAM算法进行图像分割,计算出分割图像有多少像素,然后根据像素数量计算实际面积 SAM安装及模型下载: https://github.com/facebookresearch/segment-anything?tab=readme-ov-file…

Gemini Pro 加持,谷歌 AI 笔记 Notebook LM 重磅升级!

在现在这种信息爆炸的时代&#xff0c;如何高效处理海量信息&#xff0c;已经成为困扰很多人的难题。如何整合来自不同来源的信息和想法&#xff0c;并在它们之间建立联系。这个过程&#xff0c;费时费力&#xff0c;还很容易让人抓狂&#xff0c;更别提还要从中提炼、归纳、整…

工作助手C#研究笔记(5)

通过示例对C#程序的结构逻辑进行研究梳理&#xff0c;虽然通过阅读相关书籍&#xff0c;但是来的效果更慢。一下相关内容可能有误&#xff0c;请谨慎听取。 TaskToDoList-master 1.XAML “XAML”是WPF中专门用于设计UI的语言&#xff0c;优点是 1.XAML可以设计出专业的UI和…

c# .Net Core 项目配置SWagger UI 带Token访问

简介 Swagger是一款强大的API管理工具&#xff0c;它主要用于生成、描述、调用和可视化RESTful风格的Web服务。Swagger通过一套标准的规范定义接口及其相关信息&#xff0c;从而能够自动生成各种格式的接口文档&#xff08;如HTML、PDF、Markdown等&#xff09;&#xff0c;并…

知识库、微调、AI Agent

Agent执行工作的过程是需要大模型来配合的&#xff0c;大模型充当一个大脑&#xff0c;给Agent下达指令。Agent当接收到这个指令的时候&#xff0c;然后去执行。 大模型参数的数量直接影响大模型的生成能力和推理能力&#xff0c;也直接影响了大模型的使用效果。参数越多&…

【竞技宝】奥运会:日本U23惨败梦想破裂

奥运会男足8进4的比赛已经全部结束,夺冠热门阿根廷被东道主法国淘汰,埃及点球淘汰巴拉圭,摩洛哥4比0大胜美国,亚洲球迷关心的日本U23竟然惨败西班牙U23,让不少球迷都觉得意外。因为日本U23赛前被普遍看好,可是他们却被西班牙队全面压制,甚至毫无还手之力,这样的结果让球迷们不禁…

【linux】linux中定时任务的巧妙运用,让你轻松解放双手

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

书生·共学计划|训练营又开始啦!

&#x1f970; 在大模型技术的浪潮中&#xff0c;面对混杂的众多信息&#xff0c;如何获取有效、可信的学习资源成为了一项挑战。为此&#xff0c;我们推出“书生共学计划”&#xff0c;鼓励大家将实战营活动分享给你身边有需要的小伙伴&#xff0c;让每一位热爱技术的朋友都能…

无人机培训机构开办投资收益分析

一、引言 随着无人机技术的飞速发展及其在航拍、农业、测绘、物流等多个领域的广泛应用&#xff0c;市场对无人机专业人才的需求急剧增长。因此&#xff0c;开设无人机培训机构成为了一个具有广阔市场前景的投资项目。本报告旨在全面分析无人机培训机构开办的投资收益&#xf…

面向开发者的 LLM 入门教程-笔记和代码

本文是 DLAI 课程 ChatGPT Prompt Engineering for Developers 的笔记。这门课面向入门 LLM 的开发者&#xff0c;深入浅出地介绍了如何构造 Prompt 并基于 OpenAI 提供的 API 实现包括总结、推断、转换等功能&#xff0c;是入门 LLM 开发的经典教程。 Prompt&#xff08;提示…

【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 系统初始化 -- main函数 --(十一)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

OJ-0805

题目 参考 import java.util.Arrays; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int L1 scanner.nextInt();int L2 scanner.nextInt();int[] A new int[L1];int[] B new int[L2];fo…

算法回忆录(1)

1.编程求1*2*3*4*……*n的末尾有多少个0。 #include <stdio.h>// 计算 n! 中末尾的0的个数 int count_zeros_in_factorial(int n) {int count 0;for (int i 5; n / i > 1; i * 5) {count n / i;}return count; }int main() {int n;printf("请输入一个整数 n&…

代码随想录day34 || 62不同路径 63不同路径2 343整数拆分

动归5步法 1&#xff0c;确定dp数组&#xff08;dp table&#xff09;以及下标的含义 2&#xff0c;确定递推公式 3&#xff0c;dp数组如何初始化 4&#xff0c;确定遍历顺序 5&#xff0c;举例推导dp数组 62不同路径 力扣题目链接 题目描述&#xff1a; 一个机器人…

免费分享一套SpringBoot+Vue图书(图书借阅)管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue图书(图书借阅)管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue图书(图书借阅)管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 本论文阐述了一套先进的图书管理系…

分享一个基于Node.js和Vue的游戏点单陪玩系统(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…