当前位置: 首页> 教育> 培训 > Gateway网关设置请求头乱码

Gateway网关设置请求头乱码

时间:2025/9/11 23:28:08来源:https://blog.csdn.net/qq_45079985/article/details/140921815 浏览次数:1次

问题描述:

​ 在做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) {// 重新构建新的requestServerHttpRequest 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 {@Overridepublic 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;}@Overridepublic 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) {// 重新构建新的requestServerHttpRequest 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 {@Overridepublic 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;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理threadLocal,防止内存泄漏UserContext.clear();}
    }
    
  3. 重新启动微服务,调用相关接口

    image-20240805110452046

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

关键字:Gateway网关设置请求头乱码

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: