zoukankan      html  css  js  c++  java
  • Nginx SSL 结合Tomcat 重定向URL变成HTTP的问题

    背景:1、架构是用的是tomcat+nginx,框架是单体的springboot系列;nginx配置了证书,采用https访问

    问题:发现用https访问首页之后,验证码加载不出来

    解决:经排查发现验证码后台的链接变成了http,提示跨域访问,经百度查询,使用一下方案解决:Nginx SSL 结合Tomcat 重定向URL变成HTTP的问题 - 程序员大本营 (pianshen.com)

    我采用的是第一种新增nginx配置,不需要改其它的,这个方案要求访问必须只能https访问,如果访问要求兼容https以及http的可以看一下最终解决方案(未检验)

    防止网址内容找不到,把内容复制到下面:

    问题描述

    由于要配置服务器(Nginx + Tomcat)的SSL的问题(Nginx同时监听HTTPHTTPS),但是,如果用户访问的是HTTPS协议,然后Tomcat进行重定向的时候,却变成了HTTP.

    逐步实践过程

    在网上找了一些资料,有些是通过修改Nginx配置即可解决,也有只对Tomcat配置进行调整解决的… 各说不一,以下对尝试的解决过程进行记录:

    实践一:Nginx新增配置

    HTTP协议制转为https

    Nginx代理的配置,要添加以下内容:

    location / {
        proxy_pass http://test-server;
        proxy_set_header Host $host;
        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;
    
        # 作用是对发送给客户端的URL进行修改, 将http协议强制转为https
        proxy_redirect   http:// https://;
    }

    为了方便测试proxy_redirect强制转换, http(80)、https(443)共存

    server {
        listen  80;  
        listen  443 ssl;  
        ...
    }

    重定向测试

    • JAVA CODE:

    1.  
      HttpServletResponse resp = (HttpServletResponse)response;
    2.  
      resp.sendRedirect("/static/html/index.html");

    使用HTTP协议访问nginx代理地址之后,URL被重定向为HTTPS协议了, 如下图所示:

     

    当然直接使用HTTPS协议访问, 肯定也是没有问题的,如下图所示:

     

    转发测试

    • JAVA CODE:

    1.  
      HttpServletResponse resp = (HttpServletResponse)response;
    2.  
      req.getRequestDispatcher("/static/html/index.html").forward(request, response);

    测试结果与重定向一致, 无异常情况;

    测试总结

    实际应用场景中,如果要求HTTPHTTPS协议共存的时候(请求的协议与响应的协议一致)就会出现HTTP请求被强转为HTTPS,尝试将Nginx配置proxy_redirect http:// https://;注释,最终使用HTTPS协议亦无法正常跳转;

    实践二:Tomcat新增配置

    不修改Nginx的情况下, 仅对Tomcat配置进行调整

    server.xmlEngine模块下面配置多一个以下的Valve

    1.  
      <Valve className="org.apache.catalina.valves.RemoteIpValve"
    2.  
      remoteIpHeader="X-Forwarded-For"
    3.  
      protocolHeader="X-Forwarded-Proto"
    4.  
      protocolHeaderHttpsValue="https"/>

    重定向测试

    使用HTTPS协议访问时,最终被重定向到HTTP

    转发测试

    使用HTTPS协议访问,转发动作未出现问题

    测试总结

    重定向的时候, HTTPS协议被转为HTTP,测试结果不通过。

    实践三:终极方案

    Nginx 配置

    对过程一Nginx配置进行调整注释或删除proxy_redirect,最终如下:

    location / {
        proxy_pass http://test-server;
        proxy_set_header Host $host;
        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;
    }

    Tomcat 配置

    参看:Tomcat配置

    测试过程

    HTTP协议请求

    HTTPS协议请求

     

    测试结果

    测试通过,无论使用HTTP访问还是HTTPS访问,最终返回都是根据请求的协议进行响应,问题解决。

    完整配置

    • Nginx
    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        sendfile        on;
    
        keepalive_timeout  65;
    
        upstream test-server {  
            server 10.15.16.6:8280 weight=1;
        }
    
        server {
            listen       80;
            listen       443 ssl;
            server_name  localhost;
    
            #ssl_certificate      cert.pem;
            #ssl_certificate_key  cert.key;
    
            ssl_certificate      server.crt;
            ssl_certificate_key  server.key;
    
           # ssl_session_cache    shared:SSL:1m;
           #ssl_session_timeout  5m;
    
           # ssl_ciphers  HIGH:!aNULL:!MD5;
           # ssl_prefer_server_ciphers  on;
    
    
            location / {
                proxy_pass http://test-server;
                proxy_set_header Host $host;
                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;
                # proxy_redirect   http:// https://;
            }
    
        }
    
    }

    //处理代码段

    1.  
      domainName = request.getRequestURL().toString();
    2.  
      String X_Forwarded_Proto = httpRequest.getHeader("X-Forwarded-Proto");
    3.  
      if(StringUtils.isNotBlank(X_Forwarded_Proto)){
    4.  
      if(X_Forwarded_Proto.toLowerCase().contains("https") && !domainName.toLowerCase().startsWith("https://")){
    5.  
      domainName = "https://" + domainName.substring(7);
    6.  
      }
    7.  
      }
  • 相关阅读:
    JavaScript监听、设置全部ajax访问属性获取返回值(状态码)
    如何在Vue项目中使用vw实现移动端适配
    git 常用命令金字教程
    移动web开发之像素和DPR详解
    小程序-微信开发者工具使用
    小程序开发框架:Taro(一)基础篇
    vscode代码自动补全失效
    JS、C#编码解码
    PHP网页缓存技术
    ajaxfileupload回到json带<pre>
  • 原文地址:https://www.cnblogs.com/aishangyizhihu/p/15192418.html
Copyright © 2011-2022 走看看