如何正确隐藏WordPress的版本号?

默认情况下,当你使用WordPress来搭建网站的时候,WordPress会在你的网站上留下个标记:这就是WordPress的版本号。在某些时候,这个标记也会成为网站的安全漏洞。
打开你的WordPress网站,在浏览中的空白地方点击右键,选择查看源代码,通常你会找到有这样一行代码:

<meta name="generator" content="WordPress 4.4.1" />

这是WordPress自动生成的代码,向外界宣告你所使用的WordPress版本。如果你的网站一直使用的是最新版WordPress,那你基本无需担心因为泄露版本号而导致的安全问题。但是,由于某些特殊的原因,如果你使用的是旧版本的软件,那么暴露WordPress版本号可能会成为你网站的安全漏洞。

因此,在这种情况下,你应该隐藏网站所使用的WordPress版本号。

在你的网站中,有四个地方容易暴露WordPress的版本号:

  1. 网站源码页头部分的meta标签里:
  2. 脚本和样式表文件中:
  3. 网站RSS feeds中:
  4. 网站根目录下的readme.html文件中。

网络中各种隐藏WordPress版本号的技巧很多,功能最为完整且简洁的代码,应当是属于下面这段:

<?php
	/* 在 js 文件和 css 文件中隐藏 WordPress 版本号
	 * @return {string} $src
	 * @filter script_loader_src
	 * @filter style_loader_src
	 */
	function wpchina_remove_wp_version_strings( $src ) {
		 global $wp_version;
		 parse_str(parse_url($src, PHP_URL_QUERY), $query);
		 if ( !empty($query['ver']) && $query['ver'] === $wp_version ) {
			  $src = remove_query_arg('ver', $src);
		 }
		 return $src;
	}
	add_filter( 'script_loader_src', 'wpchina_remove_wp_version_strings' );
	add_filter( 'style_loader_src', 'wpchina_remove_wp_version_strings' );
	 
	/* 在 generator meta 标签中隐藏 WordPress版本号 */
	function wpchina_remove_version() {
	return '';
	}
	add_filter('the_generator', 'wpchina_remove_version');
?>

这段代码可以移除前面3个地方中所包含的WP版本号。记得要把这段代码放在你所用主题(或子主题)的funcitons.php模板文件中。

修改完成后,如果是使用PHP-FPM来进行处理的服务器,需要重启PHP-FPM服务否则代码可能不能及时生效:

$  sudo service php5-fpm restart

对于上面第4点提到的,位于WordPress根目录下的readme.html文件,你直接删除该文件就可以了。这份文件是关于WordPress的简单介绍和安装说明,安装好账户就没有什么用途了。

如果使用的是Apache服务器,也可以简单的在根目录下面建立.htaccess文件,里面增加如下内容:

# 禁止 readme.html 的访问,这个文件会暴露版本号信息
<Files readme.html>
	order deny,allow
	deny from all
</Files>

当然,以上这些做法,隐藏了WordPress的版本号,并不能真正解决网站中所存在的安全漏洞。确保网站安全的第一要素,还是要及时更新WordPress核心软件,所使用的主题、插件;使用健壮的用户名和密码;不要使用来历不明的盗版主题和插件等。

引用链接


如何正确隐藏WordPress的版本号?

WordPress首页显示摘要(手工设置)

WordPress比较长的时间了,一直是在首页显示文章全文的,但是最近由于摘抄的某些文章中的图片非常多,导致每次加载首页会下载非常多的图片资源,整个页面加载速度都被拖慢了,于是想只在首页显示摘要,而不是全文显示。
网上搜索了一下,发现WordPress早就有这个功能了,如下图:


如果想手工编辑Html的话,只要简单的加入

<!--more-->

标签就可以达到相同的效果了。

WordPress 4.7.x版本禁用 REST API

最近WordPress频繁爆出漏洞,尤其是REST API部分,简直是漏洞百出,但是,从4.7.0版本开始,这部分功能被深度整合进入了核心模块,没办法彻底屏蔽REST API,只有通过rest_authentication_errors这个接口来限制非登陆用户,具体代码如下

<?php
	add_filter('rest_authentication_errors','disable_rest_api');
	function disable_rest_api(){
		if(!is_user_logged_in()){
			return new WP_Error('Error!', __('Unauthorized access is denied!','rest-api-error'), array('status' => rest_authorization_required_code()));
		}
	}
?>

此部分的代码需要被添加到当前主题的functions.php中的最后即可。
增加完成后,重启Apache2服务器,然后再访问https://www.mobibrw.com/wp-json/ 就可以看到错误信息了。

参考链接


解决从WordPress 4.7.1升级到WordPress 4.7.2失败后再次更新提示"另一更新正在进行"

从WordPress 4.7.1升级到WordPress 4.7.2,中途失败了,结果再次更新的时候,提示“另一更新正在进行”,如下图所示:

这是由于在升级WordPress时,WordPress会在数据库wp_options表中增加core_updater.lock记录。如中途打断WordPress升级,这个记录会留在数据库中。当下次升级时,WordPress检测到此记录的存在就会返回”另一更新正在进行”。可通过终端登录数据库删除这条记录来处理.

$ mysql -u root -p 

$ mysql> use wordpress;

$ mysql> select * from wp_options where option_name='core_updater.lock';

$ mysql> delete from wp_options where option_name='core_updater.lock';

$ mysql> exit;

如上操作之后,再次重新升级,就可以解决问题了。

参考链接


从零创建WordPress自定义插件

序曲


使用WordPress统计插件WP Statistics之后,经常会出现某个IP的访问突然出现比较多的情况,那么这个时候就需要了解这个IP访问的是哪个页面,是否发生了访问攻击。但是遗憾的是,WP Statistics并没有根据IP地址查询访问记录的功能,因此,我们就自己写一个查询插件好了。

创建插件的文件和文件夹


WordPress插件存储在wp-content/plugins/文件夹中,而我们的新建文件也要存放在这个文件夹中。一般情况下,如果所制作的插件非常简单,可直接把所有代码放在一个PHP文件中,然后把其放在wp-content/plugins/文件夹中。但是,我们这里要制作的插件要使用两个文件(一个是主要的插件文件,另一个为执行管理页面的文件),因此,我们需要把新创建的文件另放在一个文件夹中,我们这里把这个文件夹命名为wp-statistics-visitor-query

创建插件的功能文件


我们就要创建插件主要文件了,我们把其命名为wp-statistics-visitor-query.php。当然,你也可把其命名为其它名称,这并不重要。

然后再文件的头部增加插件的描述信息,如果不增加描述信息,WordPress是找不到这个插件的。增加的内容如下:

<?php
/*
Plugin Name: WP Statistics Visitors Query
Plugin URI: http://www.mobibrw.com
Description: Plugin for query WP Statistics Visitors
Author: LongSky
Version: 1.0
Author URI: http://www.mobibrw.com
*/
?>

这样操作完成后,就可以在插件管理界面中找到名字为"WP Statistics Visitors Query"的插件了。

使用行为钩子(Action Hook)


虽然插件现在已在管理面板显示,但是由于它只含有header信息,因此它并没有其它功用。现在,我们就来增加它的功能吧。
WordPress允许用户把插件代码放在模板的任意位置,包括页面的空间位置及页面创建过程中的逻辑位置。在此,我们将进一步了解后者,逻辑位置——即行为钩子。

行为钩子

我们可把行为钩子视为回调函数。WordPress执行某项操作时,如,显示页脚,它就会让插件来执行自己的代码并且要在确切的时间运行。
为了方便大家理解,我们以my_plugin这个普通插件为例,当系统显示页脚时,这个插件就会执行mp_footer()函数。因此,显示页脚时,使用名为add_action()这个特殊的函数,我们就会告知WordPress调用mp_footer()函数:

add_action()函数把行为钩子名称作为其第一个参数,同时把必须执行的函数名称作为其第二个参数。我们将把此函数调用添加到插件的主要文件(即包括header信息的文件),通常把它放在需要执行的函数代码正下方(本例中即放在mp_footer()下)。可在WordPress Codex查看所有可用的行为钩子 。

创建插件管理页面

我们要先创建新菜单条目并把其放置在设置菜单中。

WordPress提供了新建菜单可调用的钩子(即admin_menu),因此,这也是我们创建菜单条目的最佳地点。

既然已确认需使用的行为钩子,我们接着就要定义行为钩子运行时要调用的函数了,我们把其称为visitors_query_admin_actions()。代码显示如下:

<?php
function visitors_query_admin_actions() {
}
add_action('admin_menu', 'visitors_query_admin_actions');
?>

正如您所看到的,我们已创建了visitors_query_admin_actions()函数,并用add_action()函数让其与admin_menu行为钩子结合。接下来,我们就要给visitors_query_admin_actions()函数添加一些代码以创建真正的菜单条目了。

WordPress其它许多操作类似,添加新菜单条目也非常简单,只需调用一个函数就可完成!把新菜单条目添加到设置菜单需要使用add_options_page()函数,然后把以下代码添加到visitors_query_admin_actions()函数中。

<?php
function ip_admin() {
}

function visitors_query_admin_actions() {
	add_options_page("Query Visitor From IP", "Query Visitor From IP", 1, "Query Visitor From IP", "ip_admin");
}
add_action('admin_menu', 'visitors_query_admin_actions');
?>

此时刷新管理页面,设置页面下就已包括新建菜单条目了。
QueryVisitorFromIP
WordPress中的每个菜单都使用不同的函数来添加其子菜单条目。例如,如果要给工具添加子菜单条目,我们就应该使用add_management_page()函数,而非设置页面使用的add_options_page()。更多信息,请查看WordPress Codex中的添加管理菜单
重新回到新添加的代码,或许您已注意到了最后一个参数。它即是请求新增菜单条目时,系统将调用的函数,我们也将使用它来创建插件的管理页面。
我们最好把此页面功能放在单独的文件中,并给其命名为query_visitor_import_admin.php

<?php
function ip_admin() {
	include('query_visitor_import_admin.php');
}

// 只有管理员才能使用这个功能,基本安全防护
function is_administrator() {
	if( current_user_can( 'manage_options' ) ) { return True; }
	return False;  // 非管理员
}

function visitors_query_admin_actions() {
	if(is_administrator()) {
		add_options_page("Query Visitor From IP", "Query Visitor From IP", 1, "Query Visitor From IP", "ip_admin");
	}
}

add_action('admin_menu', 'visitors_query_admin_actions');
?>

此时点击设置菜单下的链接,系统将显示空白页面,这是因为query_visitor_import_admin.php文件现在没有任何内容。
接下来我们配置页面中的内容,如下:

<?php
        function ip_query($ipaddress) {
                $q = "select referred from wp_statistics_visitor where ip='$ipaddress';";
                global $wpdb;
                $rows = $wpdb->get_results($q,ARRAY_N);
                $i=0;
                while ($i< count($rows)){
                        $row = $rows[$i];
                        /*echo var_dump($row[0]);*/
                        echo "<br/>";
                        echo $row[0];
                        $i++;
                }
        }
?>
		
<div class="wrap">
	<form name="visitors_query_form" method="post" action="<?php echo str_replace( '%7E', '~', $_SERVER['REQUEST_URI']); ?>">
		<p><?php _e("IP Address: " ); ?><input type="text" name="visitors_ip" value="" size="20"><?php _e(" ex: 192.168.1.1" ); ?></p>
		<hr />
		<p class="submit">
			<input type="submit" name="Submit" value="Query" />
		</p>
	</form>
	<hr />
	<p>
		<?php
			$ipaddress = $_POST['visitors_ip'];
			_e("Query $ipaddress :");
		?>
	</p>
	<hr />
	<div>
                <?php
                        $ipaddress = $_POST['visitors_ip'];
                        if(is_administrator()) {
                                ip_query($ipaddress);
                        } else {
                                echo "only administrator can use this function";
                        } 
                 ?>
	</div>	
</div>

如此调整之后,需要禁用一下插件,然后再启用,否则可能不会生效。

代码详解


熟悉HTML和PHP的人都会理解以上代码,但我们这里仍将简单解释一下。

  • 我们首先用wrap类创建一个div,它是一个标准的WordPress类,使新建页面能够和WordPress管理版块的其它页面风格一致。
  • 表单将使用POST方法回发数据。这意味着表单数据将由同一页面接收,这样以来,我们就可添加数据库更新代码到同一文件。
  • 查询数据库的时候使用WordPress自带的全局数据库对象$wpdb来访问数据库。
  • 为了安全,我们只允许管理员权限的人员调用我们的插件功能。

参考链接


从零创建WordPress自定义插件

Ubuntu 14.04系统WordPress 4.5升级到PHP7之后执行插件升级报错“无法定位WordPress内容目录(wp-content)”

Ubuntu 14.04系统上WordPress 4.5升级到PHP7之后执行插件升级报错,

无法定位WordPress内容目录(wp-content)

如下图所示:WordPres_wp-content

这个是由于PHP升级之后,有些函数的支持出现了变化,导致调用失败。

目前已知的修复方法是修改wp-admin/includes/class-wp-filesystem-ssh2.php中的如下的几个函数:

/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function exists($file) {
	return file_exists( $this->sftp_path( $file ) );
}

/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function is_file($file) {
	return is_file( $this->sftp_path( $file ) );
}

/**
 * @access public
 *
 * @param string $path
 * @return bool
 */
public function is_dir($path) {
	return is_dir( $this->sftp_path( $path ) );
}
/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function is_readable($file) {
    return is_readable( $this->sftp_path( $file ) );
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function atime($file) {
    return fileatime( $this->sftp_path( $file ) );
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function mtime($file) {
    return filemtime( $this->sftp_path( $file ) );
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function size($file) {
    return filesize( $this->sftp_path( $file ) );
}

修改为:

/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function exists($file) {
	//return file_exists( $this->sftp_path( $file ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
		$stat = @ssh2_sftp_stat( $this->sftp_link, $file );
		if ( false === $stat ) {
			return false; 
		}
		return (true);
	}else{
		return file_exists( $this->sftp_path( $file ) );
	}
}

/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function is_file($file) {
	//return is_file( $this->sftp_path( $file ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
		$stat = @ssh2_sftp_stat( $this->sftp_link, $file ); 
		if( false === $stat ){
			return false;
		}
		$mode = $stat['mode'];
		$type = $mode & 0xf000;
		return ($type == 0x8000);
	}else{
		return is_file( $this->sftp_path( $file ) );
	}
}

/**
 * @access public
 *
 * @param string $path
 * @return bool
 */
public function is_dir($path) {
	//return is_dir( $this->sftp_path( $path ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
		$stat = @ssh2_sftp_stat( $this->sftp_link, $path );
		if ( false === $stat ) {
			return false;
		}
		$mode = $stat['mode'];
		$type = $mode & 0xf000;
		return ($type == 0x4000);
	}else{
		return is_dir( $this->sftp_path( $path ) );
	}
}

/**
 * @access public
 *
 * @param string $file
 * @return bool
 */
public function is_readable($file) {
    //return is_readable( $this->sftp_path( $file ) );
    if(version_compare(PHP_VERSION,'7.0.0','ge')){
	    $stat = @ssh2_sftp_stat( $this->sftp_link, $file );
	    if ( false === $stat ) {
	        return false; 
	    }
	    $mode = $stat['mode'];
	    return ($mode & 0x0004);
	}else{
		return is_readable( $this->sftp_path( $file ) );
	}
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function atime($file) {
    //return fileatime( $this->sftp_path( $file ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
	    $stat = @ssh2_sftp_stat( $this->sftp_link, $file );
	    if ( false === $stat ) {
	        return false;
	    }
	    return $stat['atime']; 
	}else{
    	return fileatime( $this->sftp_path( $file ) );
	}
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function mtime($file) {
    //return filemtime( $this->sftp_path( $file ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
    	$stat = @ssh2_sftp_stat( $this->sftp_link, $file );
    	if ( false === $stat ) {
        	return false; 
    	}
    	return $stat['mtime'];
	}else{
		return filemtime( $this->sftp_path( $file ) );
	}
}

/**
 * @access public
 *
 * @param string $file
 * @return int
 */
public function size($file) {
    //return filesize( $this->sftp_path( $file ) );
	if(version_compare(PHP_VERSION,'7.0.0','ge')){
	    $stat = @ssh2_sftp_stat( $this->sftp_link, $file );
	    if ( false === $stat ) {
	        return false;
	    }
	    return $stat['size'];
	}else{
		return filesize( $this->sftp_path( $file ) );
	}
}

参考链接


Work around PHP7 php-ssh2 breakage

WORDPRESS 4.5 后台/登录页面强制HTTPS

这段时间貌似服务器经常被人攻击,由于服务器已经支持HTTPS登陆,而全站SSL加密又不是那么迫切,遂考虑后台SSL加密,强制HTTPS。
设置方法如下:
修改wp-config.php

require_once(ABSPATH . 'wp-settings.php');

之前(貌似放在后面也可以),加

define('FORCE_SSL_ADMIN', true);

就能使得后台强制加密了;
而加入一行

define('FORCE_SSL_LOGIN', true);

就可以使登录页面强制加密了。

使用WordPress的子主题功能修改你的WordPress主题

相信很多朋友使用的WordPress主题都经过了自己的一些修改,好不容易折腾好了,主题的升级版发布了,要不要升级呢?升级以后,还得重新再次修改?郁闷啊!

其实,你大可不必如此烦恼,使用Wordpress的子主题功能,一切问题都可以迎刃而解!

WordPress 子主题简介

WordPress子主题也是一个主题,它继承了另一个主题——父主题——的功能,并允许你对父主题的功能进行修改,或者添加新功能。

创建一个子主题是很简单的。创建一个目录,将格式编写正确的 style.css 文件放进去,一个子主题就做成了!

只需要对 HTML 和CSS 具有基本的了解,您就可以通过创建一个非常基本的子主题 来对一个父主题的样式和布局进行修改和扩展,而不需要对父主题的文件作任何修改。

通过这样的方式,当父主题被更新的时候,您所做的修改就可以保存下来。

因为这个原因,我们强烈推荐您使用子主题的方式来对主题进行修改。

如果您对PHP, WordPress Templates,和 WordPress Plugin API有个基本的理解,理论上来讲,您可以使用子主题对父主题的每一个方面进行扩展,而不需要对父主题的文件进行任何修改。

本文将说明如何创建一个基本的子主题并解释您能用它来干什么。本文将使用 WordPress 3.0 的默认主题 Twenty Ten 作为父主题进行举例说明。

目录结构

子主题放在wp-content/themes目录下属于自己的目录里。下面的结构显示的就是子主题和它的父主题(Twenty Ten)在典型的WordPress目录结构中的位置:

  • public_html
    • wp-content
      • themes (主题存放的目录)
        • twentyten (示例中父主题Twenty Ten的目录)
        • twentyten-child (子主题存放的目录,可以任意命名)
          • style.css (子主题中不可或缺的文件,文件名必需为 style.css)

这个文件夹里面可以少至只包含一个style.css文件,也可以包含多至一个完整WordPress主题所拥有的文件:

  1. style.css (必需)
  2. functions.php (可选)
  3. Template files (可选)
  4. Other files (可选)

让我们看看它们是如何起作用的。

必需的style.css文件

style.css是一个子主题唯一必须的文件。它的头部提供的信息让WordPress辨认出子主题,并且重写父主题中的style.css文件

对于任何WordPress主题,头部信息必须位于文件的顶端,唯一的区别就是子主题中的Template:行是必须的,因为它让WordPress知道子主题的父主题是什么。

下面是一个style.css文件的头部信息的示例:

/*
Theme Name:     Twenty Ten Child
Theme URI:      http: //example.com/
Description:    Child theme for the Twenty Ten theme
Author:         Your name here
Author URI:     http: //example.com/about/
Template:       twentyten
Version:        0.1.0
*/

逐行的简单解释:

  • Theme Name. (必需) 子主题的名称
  • Theme URI. (可选) 子主题的主页。
  • Description. (可选) 子主题的描述。比如:我的第一个子主题,真棒!
  • Author URI. (可选) 作者主页。
  • Author. (optional) 作者的名字。
  • Template. (必需) 父主题的目录名,区别大小写。 注意: 当你更改子主题名字时,要先换成别的主题。
  • Version. (可选) 子主题的版本。比如:0.1,1.0,等。

*/ 这个关闭标记的后面部分,就会按照一个常规的样式表文件一样生效,你可以把你想对WordPress应用的样式规则都写在它的后面。

要注意的是,子主题的样式表会替换父主题的样式表而生效。(事实上WordPress根本就不会载入父主题的样式表。)所以,如果你想简单地改变父主题中的一些样式和结构——而不是从头开始制作新主题——你必须明确的导入父主题的样式表,然后对它进行修改。

下面的例子告诉你如何使用@import规则完成这个。

一个子主题的范例

这个例子中的父主题是Twenty Ten,我们喜欢这个主题的几乎每个部分,除了网站标题的颜色,因为我想把它从黑色的改成绿色的。使用子主题的话,只用完成以下三个简单的步骤:

  1. wp-content/themes目录下创建一个新目录,并将它命名为twentyten-child(或其他你喜欢的名称)。
  2. 将下面的代码保存在名为style.css的文件里,并将它放到新建的这个文件夹。
  3. 到WordPress的控制台>主题,然后激活你的新主题:Twenty Ten Child。
/*
Theme Name: Twenty Ten Child
Description: Child theme for the Twenty Ten theme
Author: Your name here
Template: twentyten
*/
 
@import url("../twentyten/style.css");
 
#site-title a {
    color: #009900;
}

下面一步步解释上面代码的作用:

  1. /* 开启子主题的头部信息。
  2. Theme Name: 子主题名称的声明。
  3. Description: 主题的描述(可选,也可被省略)。
  4. Author: 作者名字的声明(可选,也可被省略)。
  5. Template: 声明子主题的父主题,换言之,父主题所在的文件夹的名称,区分大小写。
  6. */子主题头部信息的关闭标记。
  7. @import规则将父主题的样式表调入
  8. #site-title a 定义网站标题的颜色(绿色),覆盖父主题中相同的样式规则。

注意 @import 规则

需要注意的是,@import 规则之前没有其他的CSS样式规则,如果你将其他的规则置于它之上,那么它将无效,并且父主题的样式表不会被导入。

使用 functions.php

不像style.css,子主题中的functions.php不会覆盖父主题中对应功能,而是将新的功能加入到父主题的functions.php中。(其实它会在父主题文件加载之前先载入。)

这样,子主题的functions.php提供了一个灵活稳定的方式来修改父主题的功能。如果你想在你的主题里加入一些PHP函数,最快的方式可能是打开functions.php文件然后加入进去。但那样并不灵活:下次你的主题升级更新了,你加入的新功能就会丢失掉。相反地,如果你使用子主题,将functions.php文件放进去,再将你想加入的功能写进这个文件里,那么这个功能同样会工作得很好,并且对于父主题以后的升级更新,子主题中加入的功能也不会受到影响。

functions.php文件的结构非常简单:将PHP起始标签置于顶部,关闭标签置于底部,它们之间就写上你自己的PHP函数。你可以写得很多,也可以写得很少,反正按你所需。下面的示例是一个基本的functions.php文件的写法,作用是将favicon链接加入到HTML页面的head元素里面。

<?php
	function favicon_link() {
		echo '<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />' . "\n";
	}
	add_action('wp_head', 'favicon_link');
?>

给主题作者的提示。事实上子主题的functions.php首先加载意味着你的主题的用户功能可插入——即子主题是可替换的——通过有条件地进行声明。例如:

if (!function_exists('theme_special_nav')) {
    function theme_special_nav() {
        //  Do something.
    }
}

用这种方式,子主题可以替换父主题中的一个PHP函数,只需要简单地对它再次声明。

模板文件

模板文件 在子主题中的表现和style.css一样,它们会覆盖父主题中的相同文件。子主题可以覆盖任何父主题模板中的文件,只需要创建同名文件就行。(注意:index.php在WordPress3.0及以上版本才能被覆盖。)

同样,这项WordPress的功能允许你修改父主题的样式功能而不用去编辑父主题的文件,并且你的修改能让你在更新父主题后继续保留。

下面是一些使用模板文件的子主题的例子:

  • 增加一个父主题没有提供的模板(例如:网站地图页面的模板,或者一单栏页面,它们在页面编辑,模板选择里是可用的)
  • 增加一个比父模板更加具体的模板(见模板级别)。(例如:新加的tag.php模板用于按tag归档的文章来代替父主题中通常的archive.php模板。)
  • 替换父主题中的一个模板.(例:使用你自己的home.php来覆盖父主题中的home.php

其他文件

除 了style.css,functions.php,index.php和home.php,子主题可以使用任何正式主题使用的类型的文件,只要文件被正确链接。打个比方,你可以使用在样式表里或者Javascript文件里链接的图标、图片,或者从functions.php文件中调用出来的额外PHP文件。

引用链接


使用WordPress的子主题功能修改你的WordPress主题

保护wp-login.php后台登陆入口

最近在观察后台的登陆统计的时候,发现来自"`乌克兰`","`美国`"的某个IP的访问数量特别多,访问记录显示是大量访问登陆页面`https://www.mobibrw.com/wp-login.php`,明显是发生了密码破解攻击。

TopVisitors

login-recorders

本来以为`WordPress 4.4`版本已经对密码的访问次数进行了限制,结果试了一下,发现完全没有任何限制,很容易导致密码穷举攻击。比较简单的解决方法是对登陆页面进行密码尝试次数限制。

最方便的是安装`Limit Login Attempts`插件即可,这个插件很久不更新了。目前从测试来看,与`WordPress 4.4`版本是兼容的。

WordPress 4.4:禁用/关闭XML-RPC

最近网站的访问量统计发现,大量的访问请求来自第三方的国家,远远超过国内的访问量,主要是来自185.130.5.165这个IP的访问量严重的异常,怀疑是遭到了密码尝试攻击,跟踪日志:

tail -f /var/log/apache2/access.log

发现如下记录大量重复出现:

185.130.5.165 - - [06/Apr/2016:10:51:44 +0800] "POST /xmlrpc.php HTTP/1.0" 200 584 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

由于我并不使用XML-RPC服务,因此考虑禁止对于xmlrpc.php的访问。

目前由于网站开启了.htacess的支持,因此,发现在.htacess中禁止文件访问是最高效的办法。

.htacess的文件尾部增加如下语句即可:

# 禁止 WordPress xmlrpc.php 请求
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>

修改后的文件内容变更为:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# 禁止 WordPress xmlrpc.php 请求
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
# END WordPress

然后重启Apache2即可。

$sudo service apache2 restart

然后就会发现访问http://www.mobibrw.com/xmlrpc.php的时候,直接返回了403禁止访问了。

参考链接:


wordpress:禁用/关闭XML-RPC
利用xmlrpc.php对WordPress进行暴力破解攻击