http从定向到https后post请求被强制转换为get请求

本文介绍了解决HTTP请求无法正确重定向至HTTPS的问题,特别是在POST请求时遇到的挑战。通过自定义过滤器实现307重定向,确保了请求方式的保留,并解决了跨域问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本公司使用耶鲁大学的cas做单点登录服务器,在org.jasig.cas.client.authentication.AuthenticationFilter(过滤拦截请求,进行身份验证)中在181行this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);出现的问题

在tomcat的web.xml中配置

<login-config>  
    <!-- Authorization setting for SSL -->  
    <auth-method>CLIENT-CERT</auth-method>  
    <realm-name>Client Cert Users-only Area</realm-name>  
</login-config>  
<security-constraint>  
    <!-- Authorization setting for SSL -->  
    <web-resource-collection >  
        <web-resource-name >SSL</web-resource-name>  
        <url-pattern>/*</url-pattern>  
    </web-resource-collection>  
    <user-data-constraint>  
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
    </user-data-constraint>  
</security-constraint>

http get 请求 都能被重定向到https get 上,但是 http post 请求不行,后台老是报requestMethod GET not supported,访问的post 方法变成了get

在网上看到了一篇博客,nginx中遇到此问题是如何解决的

server {
listen 80;
server_name *.snsprj.cn;
return 307 https://hostrequest_uri;

}

然而我的请求状态码为302

查询相关资料,摘自wikipedia

302 Found

要求客户端执行临时重定向(原始描述短语为“Moved Temporarily”)。[20]由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
新的临时性的URI应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。
如果这不是一个GET或者HEAD请求,那么浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。

注意:虽然RFC 1945和RFC 2068规范不允许客户端在重定向时改变请求的方法,但是很多现存的浏览器将302响应视作为303响应,并且使用GET方式访问在Location中规定的URI,而无视原先请求的方法。因此状态码303和307被添加了进来,用以明确服务器期待客户端进行何种反应。


307 Temporary Redirect

在这种情况下,请求应该与另一个URI重复,但后续的请求应仍使用原始的URI。 与302相反,当重新发出原始请求时,不允许更改请求方法。 例如,应该使用另一个POST请求来重复POST请求


解决办法

由于我使用的是tomcat 进行重定向的,从上文中也可以看出tomcat 默认进行的是302重定向,不符合我们的需求,那又什么办法可以解决呢?办法就是不用tomcat提供的配置,那就是我们自己后台程序处理,毕竟用人家的受限制,自己搞,想怎么弄就怎么弄。自己做的话很明显需要一个过滤器,在请求到达sevlet 之前进行处理,代码如下:

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@WebFilter(urlPatterns="/*",filterName="HttpsFilter")
/**
 *  过滤器,将http 请求转发到https请求上来
 *  重定向类型:307
 * @author FrankYuan
 *
 */
public class HttpsFilter implements Filter{
    private Logger logger = LoggerFactory.getLogger(HttpsFilter.class);
    private static final String HTTPS ="https";
    private static final int HTTPS_PORT = 8443;
    @Override
    public void destroy() {
        logger.info("------------destroy HttpsFilter --------------");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
         URL newUrl = null;
         if(request.getScheme().equals(HTTPS)) {
             chain.doFilter(request, response);
         }else {
             HttpServletRequest httpRequest = (HttpServletRequest)request;
             HttpServletResponse httpResponse = (HttpServletResponse)response;
             String queryString = httpRequest.getQueryString()==null ? "":"?"+httpRequest.getQueryString();
             httpResponse.setStatus(307);
             String requestUrl = httpRequest.getRequestURL().toString();
             URL reqUrl = new URL(requestUrl+queryString);
             logger.info("【original request-】 "+reqUrl.toString());
             newUrl = new URL(HTTPS,reqUrl.getHost(),HTTPS_PORT,reqUrl.getFile());
             //进行重定向
             logger.info("【new request-】 "+newUrl.toString());
             httpResponse.setHeader("Location", newUrl.toString());
             httpResponse.setHeader("Connection", "close");
             //允许所有跨域请求
             httpResponse.addHeader("Access-Control-Allow-Origin", "*");     
         }

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        logger.info("------------init HttpsFilter --------------");

    }

}
注意:这里又个坑,就是重定向后需要也需要解决跨域问题,不然页面ajax请求 http 地址会出现跨域问题。




<think>首先,用户的问题是:“请问nginx 配置 https 请求定向http”。这意味着用户想将所有通过 HTTPS 发起的请求定向HTTP 协议上。这通常用于将加密流量重定向到非加密流量,但请注意,这在实践中不常见,因为 HTTPS 是为了安全而设计的。用户可能是在测试或特定场景下需要这个配置。 从系统指令中,我需要: - 所有行内数学表达式用 $...$ 格式(但这里可能不涉及数学)。 - 独立公式用 $$...$$ 格式(但问题不涉及公式)。 - LaTeX 语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 参考引用的内容: - 引用[1] 展示了 HTTP定向HTTPS 的配置。 - 引用[2] 展示了同时处理 HTTPHTTPS 请求的配置。 - 引用[3] 展示了 HTTPS定向HTTP 的配置。 - 引用[4] 解释了永久重定向。 - 引用[5] 解释了 HTTPS 的好处。 用户明确要求将 HTTPS 请求定向HTTP,所以我应该基于引用[3] 来构建答案,因为它直接提供了 HTTPSHTTP定向的配置。 关键配置来自引用[3]: ``` server { listen 443 ssl; server_name //你的域名地址; ssl_certificate D:/nginx-1.23.1/ssl/域名地址.pem; ssl_certificate_key D:/nginx-1.23.1/ssl/域名地址.key; location / { return 301 http://$host$request_uri; } } ``` 这个配置监听 HTTPS 端口 443,并重定向所有请求HTTP。 用户可能还需要一个 HTTP 服务器块来处理重定向后的请求,如引用[3] 所示: ``` server { listen 8000; server_name //你的域名地址; location / { ... # 代理或其他配置 } } ``` 但在用户的问题中,他们可能想重定向HTTP 的默认端口 80 或其他端口。 步骤: 1. **理解需求**:用户想将 HTTPS 请求定向HTTP。 2. **配置服务器块**: - 一个服务器块监听 443(HTTPS),使用 SSL 证书,并重定向HTTP。 - 另一个服务器块监听 HTTP 端口(如 80)来处理实际请求。 3. **重定向指令**:使用 `return 301 http://$host$request_uri;` 或类似。 4. **注意事项**: - 需要有效的 SSL 证书来监听 HTTPS,即使重定向。 - 重定向HTTP 可能不安全,建议仅在特定场景使用。 - 确保端口和域名正确。 回答结构: - **介绍**:解释用户的需求和配置目的。 - **步骤**:逐步说明如何配置。 - **示例配置**:提供一个完整的 Nginx 配置示例。 - **注意事项**:提醒安全和最佳实践。 - **相关问题**:生成相关问题。 最后,生成相关问题: 1. 为什么需要将 HTTPS定向HTTP? 2. 如何配置 Nginx 来处理 HTTPHTTPS 同时存在的情况? 3. Nginx 重定向的常见错误和解决方法? 确保语言是中文。</think>### Nginx 配置将 HTTPS 请求定向HTTP 用户希望将所有通过 HTTPS 发起的请求定向HTTP 协议上。这在某些特定场景(如测试环境、内部网络或降级处理)可能有用,但请注意:**将 HTTPS定向HTTP 会降低安全性**,因为 HTTP 是明文传输,容易遭受中间人攻击。在生产环境中,通常建议反向操作(HTTP定向HTTPS)以保护数据安全[^5]。 以下是一个完整的 Nginx 配置方案,基于引用[3]的示例进行优化和解释。配置分为两个部分: 1. **HTTPS 服务器块**:监听 443 端口,处理所有 HTTPS 请求并重定向HTTP。 2. **HTTP 服务器块**:监听 80 端口(或其他端口),处理重定向后的实际请求。 #### 步骤说明 1. **准备 SSL 证书**: - 即使重定向HTTP,Nginx 仍需监听 HTTPS 端口(443),因此必须提供有效的 SSL 证书(如 `.pem` 和 `.key` 文件)。证书可从权威机构(如 Let's Encrypt)获取或自签名。 - 证书路径示例:`/etc/nginx/ssl/your_domain.pem` 和 `/etc/nginx/ssl/your_domain.key`。 2. **编辑 Nginx 配置文件**: - 打开 Nginx 的主配置文件(通常位于 `/etc/nginx/nginx.conf` 或 `/usr/local/nginx/conf/nginx.conf`)。 - 添加以下两个 `server` 块(替换 `your_domain` 为您的域名或 IP)。 ```nginx # HTTPS 服务器块:监听 443 端口,重定向所有请求HTTP server { listen 443 ssl; # 启用 SSL 监听 server_name your_domain; # 替换为您的域名或 IP # SSL 证书配置(必须提供) ssl_certificate /etc/nginx/ssl/your_domain.pem; # 替换为证书路径 ssl_certificate_key /etc/nginx/ssl/your_domain.key; # 替换为私钥路径 # 重定向规则:301 永久重定向HTTP location / { return 301 http://$host$request_uri; # $host 保留域名,$request_uri 保留路径 } } # HTTP 服务器块:监听 80 端口,处理实际请求 server { listen 80; # HTTP 默认端口 server_name your_domain; # 与 HTTPS 块一致 # 处理请求(示例:代理到后端应用) location / { proxy_pass http://backend_server; # 替换为后端地址(如 http://127.0.0.1:3000) proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } # 可选:定义后端服务器(如使用 upstream) upstream backend_server { server 127.0.0.1:3000; # 示例后端地址 } ``` 3. **关键配置解释**: - `return 301 http://$host$request_uri;`:使用 301 永久重定向,将 HTTPS 请求完整路径(如 `https://your_domain/path`)重定向HTTP(如 `http://your_domain/path`)。`$host` 变量保留域名,`$request_uri` 保留路径和查询参数[^4]。 - SSL 证书必须有效:即使重定向,Nginx 仍需处理 HTTPS 握手,因此证书不可省略。 - HTTP 服务器块:负责处理重定向后的流量。示例中使用了 `proxy_pass` 代理到后端,您可根据需求修改(如静态文件服务)。 4. **测试与重启 Nginx**: - 检查配置语法:运行 `nginx -t` 确保无错误。 - 重启 Nginx:执行 `nginx -s reload` 或 `systemctl restart nginx` 使配置生效。 - 验证:访问 `https://your_domain`,浏览器应自动跳转到 `http://your_domain`(查看网络请求状态码为 301)。 #### 注意事项 - **安全风险**:HTTP 传输未加密,敏感数据(如密码)可能被窃取。仅在非生产环境使用此配置[^5]。 - **证书要求**:如果域名不匹配或证书无效,浏览器会显示警告,可能阻止重定向。 - **性能影响**:重定向会增加一次请求开销,但对性能影响较小。 - **替代方案**:如果只需部分路径重定向,可在 `location` 块中添加条件,例如: ```nginx location /insecure { return 301 http://$host$request_uri; } ``` 如果您遇到问题,请检查 Nginx 错误日志(`/var/log/nginx/error.log`)排查证书或语法错误。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值