插件更新:保护下载链接

给你的下载链接添加授权,方便你出售你的任何文件

自发布插件更新检查器库以来,提出的最常见问题之一是:“如何保护我的下载链接,以便只有购买了我的插件的用户才能下载更新?”

在本文中,我将尝试在使用WP Update Server提供插件更新的上下文中回答该问题。我还将从我的一个商业插件中提供一些实际示例。

让我们开始吧。有许多方法可以确保更新下载的安全,但是大多数方法可以归结为:

  1. 给每个用户某种安全令牌。这可以是会员站点的登录名+密码,许可证密钥,或者更深奥的东西。
  2. 每当有人在其站点上安装您的插件时,都要求他们输入密钥/登录/以其他方式输入。
  3. 修改插件以将令牌附加到每个更新请求。
  4. 编写一个服务器脚本,该脚本在允许下载之前验证令牌。

选择一个安全令牌

实施前两个步骤的方式会因插件UI以及所使用的在线商店,购物车软件或成员资格插件而有很大差异。您可能已经存在某种客户身份验证机制,只需要进行一些调整即可用于更新,或者您可能需要从头开始构建自己的身份验证机制。这里没有“一刀切”的解决方案。

就个人而言,我更喜欢使用许可证密钥。每当有人购买我的Admin Menu Editor Pro插件时,订单处理脚本都会生成一个随机密钥,将其存储在数据库中,然后将密钥和下载链接发送到客户的电子邮件中。然后,当他们安装插件时,将提供一个输入许可证密钥的链接。

我不会在此处包括许可证管理代码,因为它不在本文的讨论范围内,而是为该特定插件构建的,但是用户界面看起来像这样(单击放大):

插件更新:保护下载链接-Npcink
插件更新:保护下载链接-Npcink

将令牌添加到更新请求

现在,我们如何将安全令牌添加到每个更新请求中?您可以使用addQueryArgFilter($callback)更新检查器的方法来执行此操作。回调函数将接收查询参数的关联数组。只需将令牌添加到列表中并返回修改后的数组即可。

这是一个例子:

/* ... Code that initializes the update checker ... */
 
//Add the license key to query arguments.
$updateChecker->addQueryArgFilter('wsh_filter_update_checks');
function wsh_filter_update_checks($queryArgs) {
    $settings = get_option('my_plugin_settings');
    if ( !empty($settings['license_key']) ) {
        $queryArgs['license_key'] = $settings['license_key'];
    }
    return $queryArgs;
}

使用令牌授权下载

最后,让更新服务器在允许用户下载更新之前验证安全令牌。为此,您需要创建一个自定义服务器类(请参阅扩展服务器)并至少重写该

Wpup_UpdateServer::checkAuthorization($request)方法。这是使用此方法应做的事情:

  1. 通过使用检索包含令牌的查询参数$request->param('arg_name')
  2. 验证令牌。同样,这部分取决于您。您可以在数据库中查找它,使用校验和来验证它,或进行其他操作。
  3. 如果令牌是好的,则无需执行任何特殊操作。
  4. 如果令牌无效,请调用$this->exitWithError('Error message')以输出错误并停止脚本执行。

以下是脚本的简化版本,用于为Admin Menu Editor Pro实施安全更新  。它比上面的概述要先进一些,但是总体思路是相同的。

(同样,许可证管理超出了本文的范围,因此,我省略了大多数与加载和验证许可证有关的代码。只需将verifyLicenseExists()和其他许可功能视为伪代码。)

class SecureUpdateServer extends Wpup_UpdateServer {
    protected $licenseServer;
 
    public function __construct($serverUrl, $licenseServer) {
        parent::__construct($serverUrl);
        $this->licenseServer = $licenseServer;
    }
 
    protected function initRequest($query = null, $headers = null) {
        $request = parent::initRequest($query, $headers);
 
        //Load the license, if any.
        $license = null;
        if ( $request->param('license_key') ) {
            $result = $this->licenseServer->verifyLicenseExists(
                $request->slug,
                $request->param('license_key')
            );
            if ( is_wp_error($result) ) {
                //If the license doesn't exist, we'll output an invalid dummy license.
                $license = new Wslm_ProductLicense(array(
                    'status' => $result->get_error_code(),
                    'error' => array(
                        'code' => $result->get_error_code(),
                        'message' => $result->get_error_message(),
                    ),
                ));
            } else {
                $license = $result;
            }
        }
 
        $request->license = $license;
        return $request;
    }
 
    protected function filterMetadata($meta, $request) {
        $meta = parent::filterMetadata($meta, $request);
 
        //Include license information in the update metadata. This saves an HTTP request
        //or two since the plugin doesn't need to explicitly fetch license details.
        $license = $request->license;
        if ( $license !== null ) {
            $meta['license'] = $this->licenseServer->prepareLicenseForOutput($license);
        }
 
        //Only include the download URL if the license is valid.
        if ( $license && $license->isValid() ) {
            //Append the license key or to the download URL.
            $args = array( 'license_key' => $request->param('license_key') );
            $meta['download_url'] = self::addQueryArg($args, $meta['download_url']);
        } else {
            //No license = no download link.
            unset($meta['download_url']);
        }
 
        return $meta;
    }
 
    protected function checkAuthorization($request) {
        parent::checkAuthorization($request);
 
        //Prevent download if the user doesn't have a valid license.
        $license = $request->license;
        if ( $request->action === 'download' && ! ($license && $license->isValid()) ) {
            if ( !isset($license) ) {
                $message = 'You must provide a license key to download this plugin.';
            } else {
                $error = $license->get('error');
                $message = isset($error) ? $error : 'Sorry, your license is not valid.';
            }
            $this->exitWithError($message, 403);
        }
    }
}

来源于: https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/

WP开发

WordPress中的魔术引号,以及如何摆脱它们

2019-11-6 11:59:16

WP开发

从wp-update-server日志收集统计信息

2019-11-6 17:26:42

⚠️
Npcink上的部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 link@baimu.org 或点击右侧 私信:Muze 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索