修改request请求的header请求头实现方式

 更新时间:2026年04月28日 09:54:27   作者:我真的不吃辣条  
本文介绍了在Spring Cloud Gateway中修改HTTP请求头的方法,包括直接操作ServerHttpRequest对象和创建自定义Request请求包装类两种方式,此方法可用于替换Authorization请求头中的token

问题和场景

默认http传输不能中途修改http内容, 但是有很多时候都需要去修改请求头信息来达到某些目的,比如我这个情况:

我需要去修改Authorization请求头来替换token,我在网上看了好多博客都是HttpServletRequest类的或者是想用反射解决,但是我这里(ServerHttpRequest)并不适用,于是我去求助大佬后得出2个解决方案,并且ServerHttpRequest和HttpServletRequest都适用。

如果直接set值会有如下问题:

java.lang.UnsupportedOperationException:null;

at org.springframework.http.ReadOnlyHttpHeaders.set:

解决(ServerHttpRequest)

方案一 直接开放权限

这个方法主要是为了兼容以前的代码,因为这个header到其他方法里面还会改 所以我改了header对象

 //设置为可修改的
headers= HttpHeaders.writableHttpHeaders(headers);
//设置请求头
headers.set(HttpHeaders.AUTHORIZATION,authorization);

方案二 去修改header

这个是等于重新build对象 ,貌似更方便

exchange.getRequest().mutate().header(HttpHeaders.AUTHORIZATION,authorization).build();

上面2种方法都可以实现这个效果

修改请求前:

修改请求后:

完整代码如下:

package org.dromara.soul.bootstrap.filter;

import com.alibaba.nacos.client.utils.StringUtils;
import org.dromara.soul.bootstrap.template.RedisStrTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.util.annotation.Nullable;

import javax.xml.soap.MimeHeaders;
import java.lang.reflect.Field;
import java.util.List;

/**
 * @Auther: whhh
 * @Date: 2021/4/1 10:46
 * @Description: token替换
 */

@Order(-98)
@Component
public class GetTokenFilter implements WebFilter {

    @Autowired
    private RedisStrTemplate redisStrTemplate;

    @Override
    public Mono<Void> filter(@Nullable final ServerWebExchange exchange, @Nullable final WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //判断是否包含认证头
        if (request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
            HttpHeaders headers = request.getHeaders();
            //获取认证集合
            List<String> keys = headers.get(HttpHeaders.AUTHORIZATION);
            if (keys != null) {
                //多个认证取第一个不为空的
                for (String token : keys) {
                    if (token != null && !token.equals("")) {
                        //从Redis获取token
                        String a = (String) redisStrTemplate.get(token);
                        String authorization = a.substring(1,a.length()-1);//
                        //方法一 设置为可修改的
                        headers= HttpHeaders.writableHttpHeaders(headers);
                        //设置请求头
                        headers.set(HttpHeaders.AUTHORIZATION,authorization);



                        //方法二 bulid
//                        exchange.getRequest().mutate().header(HttpHeaders.AUTHORIZATION,authorization).build();

                        if (request.getMethod() == HttpMethod.OPTIONS) {
                            exchange.getResponse().setStatusCode(HttpStatus.OK);
                            return Mono.empty();
                        }

                    }

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



}

PS:我这个filter是soul网关(shenyu)的哦,可能chain有区别,你可以参考直接创建一个filter

解决(HttpServletRequest)

你可以自定义个RemoteAddrFilter,然后通过覆盖HttpServletRequestWrapper去替换原有的方法,基于HttpServletRequest 创建SafeboxRequestWrapper对象,然后把SafeboxRequestWrapper对象作为HttpServletRequest传递下去

代码如下:

HeaderMapRequestWrapper类

package org.dromara.soul.bootstrap.filter;


import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


/**
 * @Auther: whhh
 * @Date: 2021/4/26 19:00
 * @Description:
 */
public class HeaderMapRequestWrapper  extends HttpServletRequestWrapper{
    public HeaderMapRequestWrapper(HttpServletRequest request) {
        super(request);
    }


    private Map<String, String> headerMap = new HashMap<String, String>();

    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values.add(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }
}

GetTokenFilter类

package org.dromara.soul.bootstrap.filter;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;


/**
 * @Auther: whhh
 * @Date: 2021/4/26 18:58
 * @Description:
 */
@Order(-98)
@Component
public class GetTokenFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(req);
        //校验请求request Header中是否有对应值
        String authorization = request.getParameter(HttpHeaders.AUTHORIZATION);
        if (language !=null && !"".equals(authorization)) {
            //如果get请求url中带有这个参数,则request中新增一个header
            requestWrapper.addHeader(HttpHeaders.AUTHORIZATION, authorization);
            // Goes to default servlet.
            chain.doFilter(requestWrapper, response);
        }
        // Goes to default servlet.
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一步步教你JAVA如何优化Elastic Search

    一步步教你JAVA如何优化Elastic Search

    想要榨干Java操作Elasticsearch的所有性能潜力?本指南将一步步教你如何优化Java与Elasticsearch的交互!从此,提升ES查询速度、降低资源消耗不再是难题,赶快一起来探索Java Elasticsearch优化的秘诀吧!
    2024-01-01
  • 详解Java线程同步器CountDownLatch

    详解Java线程同步器CountDownLatch

    这篇文章主要介绍了Java线程同步器CountDownLatch的相关资料,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java中与数字相关的常用类的用法详解

    Java中与数字相关的常用类的用法详解

    在我们的代码中,经常会遇到一些数字&数学问题、随机数问题、日期问题和系统设置问题等,为了解决这些问题,Java给我们提供了多个处理相关问题的类,比如Number类、Math类、Random类等等,本篇文章我们先从Number数字类和Math数学类学起
    2023-05-05
  • java数据结构与算法之中缀表达式转为后缀表达式的方法

    java数据结构与算法之中缀表达式转为后缀表达式的方法

    这篇文章主要介绍了java数据结构与算法之中缀表达式转为后缀表达式的方法,简单分析了java中缀表达式转为后缀表达式的相关实现方法与技巧,需要的朋友可以参考下
    2016-08-08
  • Java 15密封接口的4个实现约束实战指南

    Java 15密封接口的4个实现约束实战指南

    文章主要介绍了Java 15中密封接口的定义、使用、继承约束以及在不同包和模块中的访问控制规则,密封接口通过限制类的继承来提高类型安全性和封装性,支持模式匹配和未来的switch表达式改进,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • 一文带你解读所有HashMap的面试题

    一文带你解读所有HashMap的面试题

    HashMap在面试的时候,是非常容易被问到的。因为在JDK8出来之后,非常容易被问到关于HashMap的知识点,而如果对于没有研究过他的源代码的同学来说,这个可能只是说出一部分来。本文就把HashMap上面大部分会被在面试中问到的内容,做个总结,希望有所帮助
    2022-09-09
  • 关于springboot集成阿里云短信的问题

    关于springboot集成阿里云短信的问题

    这篇文章主要介绍了springboot集成阿里云短信的方法,本文通过实例代码图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • java理论基础Stream元素的匹配与查找

    java理论基础Stream元素的匹配与查找

    这篇文章主要为大家介绍了java理论基础Stream元素的匹配与查找方法的示例说明解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • 详解Spring Security中的HttpBasic登录验证模式

    详解Spring Security中的HttpBasic登录验证模式

    HttpBasic登录验证模式是Spring Security实现登录验证最简单的一种方式,也可以说是最简陋的一种方式,这篇文章主要介绍了Spring Security的HttpBasic登录验证模式,需要的朋友可以参考下
    2019-11-11
  • Jmeter参数化实现方法及应用实例

    Jmeter参数化实现方法及应用实例

    这篇文章主要介绍了Jmeter参数化实现方法及应用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论