解決故障碼400,“”The plain HTTP request was sent to HTTPS port“”


Nginx HTTP服務器的報錯“400 Bad Request: The plain HTTP request was sent to HTTPS port”,本文將講解如何解決這個問題。簡單從報錯的字面意思上來看,是因為HTTP請求被發送到HTTPS端口,這種報錯多出現在Nginx既處理HTTP請求又處理HTTPS請求的情況。

以下是Nginx常用的SSL配置(出於安全原因,我們使用了本站域名),配置文件將讓Nginx偵聽80和443端口,並將所有的HTTP請求重定向到HTTPS:

server {
    listen       443;
    server_name blog.yoodb.com;
    charset UTF-8;
    ssl on;
    ssl_certificate   /usr/local/nginx/conf/ssl/blog/2539791_blog.yoodb.com.pem;
    ssl_certificate_key  /usr/local/nginx/conf/ssl/blog/2539791_blog.yoodb.com.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    if ($scheme = http) {
        return 301 https://$host$request_uri;
    }
    location / {
        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 https;
        proxy_pass http://172.17.6.114:8082;
    }
    location ~*/upload/images/ { 
    expires 1h;
        root /mnt/app/project/files;
    }
    location ~*/dynamic/images/ {
    expires 1h;
        root /mnt/app/project/files;
    }
}

以上的配置看上去都很正常,但是用戶請求如果通過80端口來訪問網站時,例如使用http://blog.yoodb.com,那么這個請求就會在瀏覽器收到錯誤nginx 400 bad request“The plain HTTP request was sent to HTTPS port”,示例圖片如下:

1.png

Nginx報這種錯誤是因為每一次用戶請求試圖通過HTTP訪問你的網站,這個請求被重定向到HTTPS。於是Nginx預計使用SSL交互,但原來的請求(通過端口80接收)是普通的HTTP請求,於是會產生錯誤。

另一方面,如果一個用戶使用https://blog.yoodb.com訪問網站,他們就不會遇到上述錯誤。此外,如果你有其他的網站配置為不使用SSL,Nginx會嘗試使用HTTPS,這種情況下也會造成上述錯誤。

解決辦法:

將上面配置文中的“ssl on; ” 注釋掉或者修改成 “ssl off;”;“listen 443;”修改為“listen 443 ssl”;新增“listen 80”,這樣Nginx就可以同時處理HTTP請求和HTTPS請求了,具體參考如下:

server {
    listen       80
    listen       443 ssl;
    server_name blog.yoodb.com;
    charset UTF-8;
    ssl_certificate   /usr/local/nginx/conf/ssl/blog/2539791_blog.yoodb.com.pem;
    ssl_certificate_key  /usr/local/nginx/conf/ssl/blog/2539791_blog.yoodb.com.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    if ($scheme = http) {
        return 301 https://$host$request_uri;
    }
    location / {
        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 https;
        proxy_pass http://172.17.6.114:8082;
    }
    location ~*/upload/images/ { 
        expires 1h;
        root /mnt/app/project/files;
    }
    location ~*/dynamic/images/ {
        expires 1h;
        root /mnt/app/project/files;
    }
}

java redirect重定向https跳轉http問題,如果https訪問nginx通過nginx proxy_pass到http的tomcat服務正常能夠訪問,但是java redirect就跳轉到http,導致報錯“400 Bad Request: The plain HTTP request was sent to HTTPS port”。

解決辦法:

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 https;
proxy_pass http://172.17.6.114:8082;
proxy_redirect http:// https://;

實現流程是根據nginx的不同執行階段,來完成Location http到https。

1)proxy_pass執行前,先設置了request head host 為https外網訪問的域名+端口

2)proxy_pass執行后,tomcat結果返回response

3)proxy_redirect修改response中的location中的協議http為https外網訪問的協議。

注:java redirect重定向主要是通過訪問tomcat服務的請求head項來決定的,默認是http協議,域名是通過讀取host地址,默認host中不包括訪問端口。

本文轉自:https://blog.yoodb.com/yoodb/article/detail/1527


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM