首页 > 系统相关 >解决Nginx 反代 Tomcat/Springboot 出现的ContextPath, RequestURI, getScheme, ServerPort不对的问题

解决Nginx 反代 Tomcat/Springboot 出现的ContextPath, RequestURI, getScheme, ServerPort不对的问题

时间:2022-12-13 17:00:59浏览次数:53  
标签:反代 String temp ContextPath request Tomcat proxy import public

问题示例

从/amp 反代到 /crm

 

请求地址:
 
打印信息(重复斜杠解决首页问题的, 略)

 

 

 

能看到contextPath是tomcat自己的/crm 而不是浏览器请求的/amp
这样就有可能导致模板引擎(JSP, Thymeleaf之类)请求头拼接错误而导致的404
也有可能导致后台进行Redirect的时候404

 

解决方案

继承HttpServletRequestWrapper类, 重写getContextPath, getRequestURI, getRequestURL, getScheme, getServerPort后两个解决nginx反代https时候的问题

nginx 配置

       location /amp {
            proxy_pass  http://127.0.0.1:8081/crm/;
            proxy_set_header   Host             $host;
            proxy_set_header   Port             $server_port; # 配合java代码
            proxy_set_header   Request-URI      $request_uri; # 配合java代码
            proxy_set_header   Context-Path     /amp; # 配合java代码
            proxy_cookie_path  /crm             /amp;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto $scheme; # 配合java代码
        }

HttpServletRequestWrapper

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 对nginx转发后的contextPath进行匹配修复
 * @author xudaz
 */
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
public class ParameterRequestWrapper extends HttpServletRequestWrapper {

    private final String oldContextPath;
    private final String oldRequestURI;

     ParameterRequestWrapper(HttpServletRequest request) {
         super(request);

         oldContextPath = request.getContextPath();
         oldRequestURI = request.getRequestURI();
    }

    @Override
    public String getContextPath() {
        String unknown = "unknown";
        //先从nginx自定义配置获取
        String contextPath = super.getContextPath();
        String temp = getHeader("Context-Path");
        if (temp != null && temp.length() > 0 && ! unknown.equalsIgnoreCase(temp)) {
            contextPath = temp;
        }
        return contextPath;
    }

    @Override
    public String getRequestURI() {
         // 把requestURI 的 oldContextPath 部分替换成 新的 contextPath
        String requestURI = super.getRequestURI();
        if ( requestURI.startsWith(oldContextPath) ) {
            requestURI = getContextPath() + requestURI.substring(oldContextPath.length());
        }
        return requestURI;
    }

    @Override
    public StringBuffer getRequestURL() {
        // 把 RequestURL 的 oldRequestURI 部分替换成 新的 oldRequestURI
        StringBuffer requestURL = super.getRequestURL();
        String toString = requestURL.toString();
        if ( toString.endsWith(oldRequestURI) ) {
            requestURL.replace(
                    toString.indexOf(oldRequestURI), toString.indexOf(oldRequestURI) + oldRequestURI.length()
                    , getRequestURI());
        }
        return requestURL;
    }

    @Override
    public String getScheme() {
        String unknown = "unknown";
        //先从nginx自定义配置获取
        String scheme = super.getScheme();
        String temp = getHeader("X-Forwarded-Proto");
        if (temp != null && temp.length() > 0 && ! unknown.equalsIgnoreCase(temp)) {
            scheme = temp;
        }
        return scheme;
    }

    @Override
    public int getServerPort() {
        String unknown = "unknown";
        //先从nginx自定义配置获取
        int serverPort = super.getServerPort();
        String temp = getHeader("Port");
        if (temp != null && temp.length() > 0 && ! unknown.equalsIgnoreCase(temp)) {
            serverPort = Integer.parseInt(temp);
        }
        return serverPort;
    }

}

还没完 这是新的request, 还得用上 写个过滤器 对request对象进行替换

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 替换适配nginx反代的request对象的过滤器
 * @author xudaz
 */
@Component
public class ParamsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ParameterRequestWrapper paramsRequest = new ParameterRequestWrapper(  (HttpServletRequest) request);
        chain.doFilter(paramsRequest, response);
    }

    @Override
    public void init(FilterConfig arg0)   {
    }

    @Override
    public void destroy() {
    }
}

欧克 效果↓

 

 

 

标签:反代,String,temp,ContextPath,request,Tomcat,proxy,import,public
From: https://www.cnblogs.com/lasding/p/16979287.html

相关文章

  • 如何在Idea中使用Tomcat
    在Idea中使用Tomcat有两种方式:集成本地的Tomcat,即可在idea中启动Tomcat,不需要打包好再放到tomcat中的webapps目录中(1)点击AddConfiguration...(2)在弹窗中点击左上角......
  • tomcat下载安装步骤
    下载安装tomcat官网配置环境变量CATALINA_HOME在系统变量中找到path%CATALINA_HOME%in%CATALINA_HOME%lib运行最好以管理员身份打开cmd,然后进入tomcat的bi......
  • 基于Docker构建CentOS7_Java8_Tomcat8.5 的镜像及Web应用的部署
    写在前面公司项目去​​Oracle​​​用​​teleDB​​,都在容器上部署,所以系统的学习下,之前着急忙慌的。本博客笔记属于​​实战类​​,适用于小白博文有错误的地方,或者关于博......
  • Tomcat 配置web项目
    1.首先你需要安装好Tomcat然后启动它,并将你下载的java的web项目源码放在tomcat目录的看到这个界面就是启动成功了2.然后将你的javaweb源码存放在tomcat的webapps目录......
  • 如何将springboot转称外置tomcat启动
    正常情况下,我们开发SpringBoot项目,由于内置了Tomcat,所以项目可以直接启动,部署到服务器的时候,直接打成jar包,就可以运行了(使用内置Tomcat的话,可以在application.yml......
  • win系统更改tomcat启动后dos窗口的标题名称
      检索的关键字:set _EXECJAVA=start01、更改文件的位置  02、更改的内容 ......
  • Tomcat 安装
    1、Toncat下载通过访问Tomcat官方网站下载Tomcat文件。下载地址:http://tomcat.apache.org/Tomcat提供了压缩版和安装版,还区分32位和64位系统版。下载的时候注意分......
  • IDEA中tomcat配置及项目启动
    1.tomcat下载https://tomcat.apache.org/download-80.cgi2.idea中配置注意下面的context上下文一定要改,就是服务运行时默认的起始路径地址启动项目......
  • tomcat打印日志乱码问题
    对于tomcat打印中文乱码问题,处理方式如下:找到tomcat安装目录下的conf目录,在里面找到logging.properties文件修改logging.properties文件中设置的编码格式,主要......
  • Tomcat使用介绍
    一、tomcat介绍Tomcat服务器是一个免费的开放源代码的轻量级Web应用服务器,如apache处理静态HTML能力突出不同,tomcat处理动态HTML能力相当强大,因此一般项目都是部署apache......