禁用wordpress xmlrpc.php

xmlrpc.php 是 WordPress 中一个用于支持远程发布和管理功能的接口文件。它允许第三方的应用程序(例如,桌面博客编辑器、移动应用等)通过 XML-RPC 协议与你的 WordPress 网站进行通信和操作。

为什么 xmlrpc.php 会被恶意扫描?

xmlrpc.php 已经成为黑客和恶意程序的主要攻击目标,原因如下:

  • 暴力破解攻击 (Brute Force Attack)xmlrpc.phpwp.getUsersBlogs 或类似方法允许攻击者用一个请求尝试成百上千个用户名和密码组合。这比通过传统的登录页面(wp-login.php)进行攻击要高效得多,因为后者通常需要为每次尝试都进行一次新的页面加载,更容易被安全插件检测和阻止。
  • DDoS 攻击 (Distributed Denial-of-Service):攻击者可以利用成千上万个 WordPress 网站的 xmlrpc.php 的 pingback 功能,指挥它们同时向一个目标网站发送大量请求,形成大规模的分布式拒绝服务攻击,耗尽目标服务器的资源。

正是因为这些原因,即使是全新的网站,也会立即被自动化程序扫描 xmlrpc.php,这会导致你的 VPS 或主机 CPU 和内存资源被大量消耗,出现网站卡顿甚至宕机的情况。

如何彻底解决 xmlrpc.php 的问题?

方法一:nginx location禁用

在网站nginx配置中添加:

    location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
    }

方法二:通过主题的 functions.php 文件添加代码

如果你不想安装额外的插件,可以将以下代码添加到你当前使用的主题的 functions.php 文件中。

add_filter( 'xmlrpc_enabled', '__return_false' );

这行代码会告诉 WordPress 禁用 XML-RPC 功能。

注意:如果你更换了主题,需要重新在新主题的 functions.php 文件中添加此代码。

Cloudflare Cache Rules搭配Page Rules实现灵活缓存

之前有写过Cloudflare Page Rules缓存全站的用法,但是遇到像部分页面不能缓存(类似于动态获取参数等)的时候,Page Rules设置就不够灵活了,而且cloudflare免费账户的3条Page Rules规则,明显不够用,我们就需要配合Cache Rules来使用。

Cache Rules比Page Rules的设置更加灵活方便,而且免费账户支持10条规则。

使用Cache Rules之前,需要先搞清楚它与Page Rules之间的区别:

  1. Cache Rules的优先级高于Page Rules。也就是说,如果Cache Rules中的规则与Page Rules冲突,Cache Rules规则会覆盖Page Rules规则。这就非常适合上面说的情况,用Cache Rules来排除某些不需要缓存的页面。
  2. Cache Rules规则从上往下,权重是递增的。也就是说,如果规则有冲突,下面的规则会覆盖上面的规则。

详细说明参考Cloudflare官方:https://developers.cloudflare.com/cache/how-to/cache-rules/

下面以wordpress为例,来设置Cloudflare Cache Rules搭配Page Rules实现灵活缓存规则。相比之前的设置,做了进一步的优化。

Page Rules规则

  1. URL: www.168itw.com/wp-admin*
    Cache Level: Bypass
    Disable Performance
  2. URL: www.168itw.com/*php*
    Cache Level: Bypass
    Disable Performance
  3. URL: www.168itw.com/*
    Cache Level: Cache Everything
    Edge Cache TTL: a day

规则1不缓存wordpress后台。

规则2不缓存特殊动态页面,比如动态支付页面,动态API页面,这就需要根据自己的页面结构来确定URL特性;当然这里也包括了wordpress后台登录页面wp-login.php。

规则3缓存全站,包括首页,缓存时间为1天。

Cache Rules规则

以影视站点为例,我需要用nginx对电视剧频道的视频鉴权防盗链(Nginx secure_link模块给网站添加防盗链),所以该频道页面需要动态生成鉴权token,因此不能按照Page Rules规则来缓存1天。

  1. Rule name: tv channels cache rule
    When incoming requests match…
    URI Path – Contains – /tv And
    Hostname – equals – www.168itw.com
    Cache status
    Bypass cache
    Browser TTL
    Respect origin
  2. Rule name: css & js & woff & img cache rule
    When incoming requests match…
(http.request.uri contains ".css") or (http.request.uri contains ".js") or (http.request.uri contains ".woff") or (http.request.uri contains ".jpg") or (http.request.uri contains ".png") or (http.request.uri contains ".svg") or (http.request.uri contains ".gif") or (http.request.uri contains ".bmp") or (http.request.uri contains ".ico")

Cache status
Eligible for cache
Edge TTL
7 days
Browser TTL
Override origin – 1 day

这里需要说明下:

规则1中Browser TTL设置为Respect origin,即浏览器缓存,按照默认的浏览器缓存设置来,默认设置在cloudflare的Caching – Configuration中,默认是30minutes,你也可以根据需要来修改。因为我的nginx鉴权设定为3小时,所以用户浏览器缓存30分钟是完全没问题的。

规则2是缓存css、js、woff字体、jpg等图片,因为规则1排除了tv目录下所有页面的缓存,但是这些页面上的静态资源是可以缓存的;当然,该条规则也会覆盖掉Page Rules中对于静态规则的缓存设置,因为它的优先级比较高。

不用插件给wordpress文章生成二维码

调用二维码的API接口可以直接给文章生成二维码,不需要安装插件,很方便。

1、Google API接口

<img src="https://chart.googleapis.com/chart?cht=qr&chs=200x200&choe=UTF-8&chld=L|1&chl=<?php the_permalink(); ?>" width="200" height="200" alt="<?php the_title(); ?>" />

2、qrserver API接口

<img src="http://api.qrserver.com/v1/create-qr-code/?size=200x200&data=<?php the_permalink(); ?>" alt="<?php the_title(); ?>"/>

国内的话,Google API被屏蔽,qrserver速度很慢。

另外,wordpress的二维码插件,有的也是调用Google和qrserver的接口,有的是生成二维码图片存储在本地服务器,可以参考这篇文章:https://blog.brain1981.com/1362.html

wordpress开启多站点网络

1、打开wp-config.php配置文件,将以下代码插入到 /* That’s all, stop editing! Happy publishing. */ 前一行:

define('WP_ALLOW_MULTISITE', true);

2、刷新wordpress后台,在 工具 – 网络配置 中,配置多站点网络。

3、按照提示,将代码复制到wp-config.php文件中保存。

4、伪静态规则。如果选择了用二级目录作为多站点,用的宝塔面板,选择伪静态规则wp2,或者复制以下代码:

rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=$1 last;
if (!-e $request_filename){
	rewrite ^.+?(/wp-.*) $1 last;
	rewrite ^.+?(/.*\.php)$ $1 last;
	rewrite ^ /index.php last;
}

如果是选择二级域名为多站点,宝塔伪静态规则选择wordpress即可。

5、如果登录后台控制台,出现重定向太多的错误,无法登录,找到:

** 
@package WordPress
*/

在下方添加如下代码:

$_SERVER['HTTPS'] = 'on';
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

6、给网站添加hreflang多语言标签:

移除wordpress版本及相关服务代码,提高安全

前面有关于移除wordpress rss feed防采集:

移除wordpress版本及相关服务代码,可以提高安全,汇总!

文章来自于我爱水煮鱼的博客,原文链接在最后。

版本号

​WordPress 会在页面头部显示你的 WordPress 版本号:

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

作为博主的你,当然知道自己所使用的 WordPress 版本了,但是使用的 WordPress 版本直接暴露在外面,反而是一个安全隐患,万一你的 WordPress 一时没有升级,而这个版本刚好有安全问题,然后又给坏人知道了,那就造成安全问题,所以最好不要暴露在页面:

remove_action('wp_head', 'wp_generator');

RSD

Really Simple Discovery(RSD)是XML格式的一种发布约定,用于使 WordPress 可以被客户端软件发现,这是一种将客户端软件所需的信息减少到三个众所周知的元素的方法:用户名,密码和主页URL,其他关键设置都在 RSD 文件中定义。它会在页面头部输出代码如下:

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://example.com/xmlrpc.php?rsd" />

简单说 XML-RPC 客户端发现机制需要用到,一般建议在使用 XML-RPC 客户端时候开启即可,其他时候建议关闭,省的被人使用 XML-RPC 客户端来尝试登录。

remove_action('wp_head', 'rsd_link');

wlwmanifest

wlwmanifest 是用来说明支持 Windows Live Writer ,它会在页面头部输出代码如下:

<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://example.com/wp-includes/wlwmanifest.xml" />

如果你没有使用 Windows Live Writer 来写文章,那就移除它吧:

remove_action('wp_head', 'wlwmanifest_link');

这个原本的意图是如果你的文章的固定链接很长,告诉用户可以通过 http://example.com/?p=13150 这个的短链接的方式快速访问。它会在文章详情页的页面头部输出代码如下:

<link rel='shortlink' href='http://example.com/?p=13150' />

但是这个可能暴露文章的 ID,而你不想让人知道的话,那就最好移除它:

remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0);

REST

它会在文章详情页的页面头部输出代码如下:

<link rel="https://api.w.org/" href="https://blog.wpjam.com/wp-json/" />

这个代码是用来告诉 APP 开发者,当前站点的 REST API 的地址,这个口头告诉一下就行了,没有必要在代码中输出:

remove_action('wp_head', 'rest_output_link_wp_head', 10);

汇总

汇总一次,将上面所有代码都复制到主题的 functions.php 就能一次性移除了:

remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0);
remove_action('wp_head', 'rest_output_link_wp_head', 10);
继续阅读

wordpress输出文章别名post_name

<?php global $post; $post_slug = $post->post_name; ?>

输出:

<?php echo $post_slug; ?>

或者直接用:

<?php global $post; $post_slug=$post->post_name; echo $post_slug; ?>

另外一种方法是:

<?php $post_slug = get_post_field( 'post_name', get_post() ); ?>

进一步,如果要输出自定义字段的值,可以用:

<?php echo get_post_meta(get_the_ID(), 'key1', true); ?>

延伸:

wordpress常用函数:https://codex.wordpress.org/Function_Reference

wordpress全局变量:https://codex.wordpress.org/Global_Variables

wordpress更新提示“另一更新正在进行”

更新升级wordpress的时候出现“另一更新正在进行”错误提示,这种情况,一般出现在更新升级中断后,再次点击升级时。解放方法也很简单:

方法一、通过MySQL数据库管理工具(比如 phpMyAdmin),在 wp_options表中找到 core_updater.lock记录并将这一列数据删除。

方法二、通过终端登录数据库,假设表前缀是wp_,数据库是wordpress,

mysql -u root -p

use wordpress;

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

修改wordpress图片默认保存路径为二级域名

WordPress默认是将多媒体文件存放在/wp-content/uploads/目录下。

1)wordpress3.5版本后在设置>>多媒体中找不到媒体路径的选项

不过我们可以通过下面的代码重新找回设置选项,将代码添加到主题目录的functions.php文件中。

//找回上传设置
if(get_option('upload_path')=='wp-content/uploads' || get_option('upload_path')==null) {
 update_option('upload_path',WP_CONTENT_DIR.'/uploads');
}
//找回上传设置结束

2)在后台>>设置>>多媒体中能看到如图增加的功能选项

修改保存路径为二级域名目录。

wordpress编辑器无法找到主页的区块模板

新安装的wordpress出现以下两种错误:

  1. 编辑网站的时候,提示“编辑器无法找到主页的区块模板”;
  2. 发布文章的时候,提示“发布失败。 您可能已经掉线。”

如果你网站有ssl证书,可能就是https引起的,解放方法也很简单:

在设置中,将“wordpress地址(URL)”和“站点地址”,两处的url前面的http改成https

改完后,如果发现无法进入wordpress后台,参看之前的文章:

WordPress添加https后出现重定向太多无法打开的错误

wordpress批量删除指定分类所有文章

文章数量不多,可以直接后台手动删除,如果数量很多,需要执行SQL:

delete
from
wp_posts
using
wp_posts,
wp_term_relationships,
wp_term_taxonomy
where
wp_posts.id = wp_term_relationships.object_id
and
wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
and
wp_term_relationships.term_taxonomy_id = 18(分类ID)

如果还需删除分类:

delete FROM `wp_term_relationships` where term_taxonomy_id = 18(分类ID)

如果需要删除指定post_type所有文章,执行:

DELETE FROM wp_posts WHERE post_type='post_type';
DELETE FROM wp_postmeta WHERE post_id NOT IN (SELECT id FROM wp_posts);
DELETE FROM wp_term_relationships WHERE object_id NOT IN (SELECT id FROM wp_posts)

另外,update更新内容的用法:

UPDATE wp_posts SET post_content = replace( post_content, '原内容','新内容') WHERE option_name = 'home' OR option_name ='siteurl';