WordPress更换https出现的奇怪问题

发布于 2020-03-02  100 次阅读


更换完https,成功运行了大概三到四天,突然出现混合请求(https请求包含了http,被浏览器拦截),贼迷。。。

故事背景

为了服务器能接入百度的智能语音api,支持https是必须的。既然给域名申请了ssl证书,那索性把博客也改成https访问。

然后就开始一通配置,因为这个放博客的vps使用的是cpanel控制面板,所以权限是被限制的,但搭博客啥的就很方便,环境都配好了,控制面板也提供了包管理,快速安装相关软件,自动管理ssl证书,重定向,子域名等等。

ps:这里的重定向可以用来代替域名解析的显性url(如果你的域名没有备案的话)

所以就在控制面板上开启了ssl和https访问,然后把所有http访问重定向成https,在wordpress管理控制台把域名也改成https,然后就能成功挂上小锁了!!

但是,问题又来了,在成功运行了大概三到四天之后,突然出现混合请求(https请求包含了http,被浏览器拦截) 。我:??????。

我这啥也没动啊怎么就这样了?而且前面不是跑得好好的?

排查问题

于是先f12,看看哪里出现了混合请求,发现是各个页面的模板里都出现了http引用。各种css和图片都是http的链接,文章部分又是好的。

我又:????那前面为啥跑得好好的。

于是排查了一下所使用的主题内部有没有使用了http的硬链接,结果并没有。

于是怀疑一下wordpress本身的链接是否出现了http的绝对路径,但因为在控制台已经把站点地址修改成https了,感觉没太大可能性。

于是又把wordpress的数据库打开,执行替换,把所有http替换成https。然并卵,而且并没有相关的条目。

我继续:?????那为啥前面跑得好好的。

于是我在绝望中选择备份并重装。。。一样的问题。。

啊。。。鲨了我吧

问题解决

最后死马当活马医,搜了n多教程,说啥没强制开启ssl访问。于是我就不抱希望的试了一下:

  • 打开wordpress根目录, wp-config.php。
  • 添加以下内容
  • $_SERVER['HTTPS'] = 'on';
  • define('FORCE_SSL_LOGIN', true);
  • define('FORCE_SSL_ADMIN', true);
  • 保存

然后。。就成了?????

我更:??????了

解决之后

最后发现问题出在$_SERVER['HTTPS'] = 'ON';这条语句上,直接设置环境变量。通过查询相关案例,有出现过同一台服务器上通过$_SERVER拿到的环境变量有的是https,有的是null,这样也就导致某些使用了相对路径的请求使用了http。

这样在设置之后,即使是通过http访问,内部的资源也全部都是https链接的。

这种问题的实质还是服务器上的fastcgi配置有问题,如果使用了nginx, 默认不会将HTTPS传递给PHP-FPM ,也就拿不到环境变量。但apache就可以。 (本机上无权限,无法测试) 这里贴出其他人的配置。

nginx样例例:

location ~ .*\.(php|php5)?$
{
 try_files $uri =404;
 fastcgi_pass  unix:/tmp/php-cgi.sock;
 fastcgi_param HTTPS $https if_not_empty;
 fastcgi_index index.php;
 include fastcgi_params;
}

其中fastcgi_param HTTPS $https if_not_empty;这一条就是设置环境变量。意思就是查询链接类型,如果为空,则忽略。

如果想网站强制https访问,则可以把这条变量写死,变成:

<strong>FASTCGI_PARAM HTTPS </strong>on

这和在wordpress里把环境变量写死是一个道理。但在这里改会对所有使用了该环境变量的程序生效。

方法汇总

在服务器ssl证书配置完毕的前提下,开始对wordpress进行修改。

  • 在wordpress 的管理页面,把站点地址修改成https协议的,同步更改站点内的链接地址,媒体地址。
  • 找到网站根目录,修改 wp-config.php,添加以下条目。
$_SERVER['HTTPS'] = 'ON';
DEFINE('FORCE_SSL_LOGIN', TRUE);
DEFINE('FORCE_SSL_ADMIN', TRUE);
  • 数据库替换,防止旧链接仍然是http协议的 :(不推荐这样操作)

<strong>update wp_posts set post_content = replace(post_content, 'http://example.com','https://example.com'); </strong>

  • wp主题内链接替换(可代替数据库替换)

编辑当前主题下的 functions.php 文件,加入以下代码:

//绝对路径替换
add_filter('get_header', 'fanly_ssl');
function fanly_ssl(){
	if( is_ssl() ){
		function fanly_ssl_main ($content){
			$siteurl = get_option('siteurl');
			$upload_dir = wp_upload_dir();
			$content = str_replace( 'http:'.strstr($siteurl, '//'), 'https:'.strstr($siteurl, '//'), $content);
			$content = str_replace( 'http:'.strstr($upload_dir['baseurl'], '//'), 'https:'.strstr($upload_dir['baseurl'], '//'), $content);
			return $content;
		}
		ob_start("fanly_ssl_main");
	}
}
//相对路径替换
add_filter('get_header', 'fanly_ssl');
function fanly_ssl(){
	if( is_ssl() ){
		function fanly_ssl_main ($content){
			$siteurl = get_option('siteurl');
			$upload_dir = wp_upload_dir();
			$content = str_replace( 'http:'.strstr($siteurl, '//'), strstr($siteurl, '//'), $content);
			$content = str_replace( 'http:'.strstr($upload_dir['baseurl'], '//'), strstr($upload_dir['baseurl'], '//'), $content);
			return $content;
		}
		ob_start("fanly_ssl_main");
	}
}
  • nginx配置文件修改(别照搬,这里只是样例),重点是fastcgi_param HTTPS $https if_not_empty;
location ~ .*\.(php|php5)?$
{
 try_files $uri =404;
 fastcgi_pass  unix:/tmp/php-cgi.sock;
 fastcgi_param HTTPS $https if_not_empty;
 fastcgi_index index.php;
 include fastcgi_params;
}

当其他人都认为你要鸽的时候,你鸽了,亦是一种不鸽