anders/fortress

一个用于对HTTP请求数据进行白名单、验证和规范化的PHP库,与JSON模式进行对比

v4.1.1 2017-07-11 02:33 UTC

This package is auto-updated.

Last update: 2024-09-29 05:08:02 UTC


README

版权所有 (c) 2015-2017

一个基于模式驱动的系统,优雅地在客户端和服务器端进行用户输入的白名单、转换和验证,基于一组统一的规则。

介绍

外部世界的数据是现代交互式网络服务和应用的阿基里斯之踵。当网络应用接受其不应接受的用户输入,或未能中和输入中的有害部分时,代码注入、跨站脚本(XSS)、CSRF和其他许多类型的恶意攻击就会成功。即使是非恶意用户也可能无意中提交一些破坏您的网络服务的东西,导致它以某种意想不到的方式运行。

为了安全和良好的用户体验,网络开发者必须做两件事

  1. 决定您的应用程序应接受哪种类型的输入,并且;
  2. 决定当您的应用程序接收到违反这些规则的内容时,应该如何表现。

听起来很简单,对吧?不幸的是,即使是经验丰富的开发者也常常出错,让恶意用户在应用程序的服务器上执行SQL或PHP(在XSS和CSRF攻击的情况下,允许用户欺骗其他用户执行恶意代码)。

问题的一部分在于,这种过滤必须在用户可以向服务器提交原始数据的每个应用点进行。现代网络应用可能接受数百种不同的POST请求,手动编写每个请求的规则可能会变得极其繁琐。其中大部分工作必须在客户端(为了用户体验)和服务器端(为了安全)进行。

Fortress通过提供客户端(在JavaScript中)和服务器端(在PHP中)使用单一统一规则集验证原始用户输入的统一接口来解决此问题。您只需创建一个请求模式,它定义了您期望用户提交的字段以及如何处理这些字段的内容的规则。例如,您可能想要检查电子邮件地址是否格式正确。请求模式(一个简单的YAML或JSON文档)使得在单个位置操作这些规则变得容易。

请求模式可以在服务器端应用于接收到的请求数据,也可以转换为与客户端验证库兼容的格式,例如jQuery Validation插件,这使得在没有必要编写每个规则两次的情况下,很容易进行客户端和服务器端验证。

一个使用WDVSS标准编写的请求模式示例

schema.yaml

name: 
    validators: 
        length: 
            min: 1
            max: 200
            message: Please enter a name between 1 and 200 characters.
        required : 
            message : Please specify your name.

email: 
    validators: 
        required: 
            message: Please specify your email address.

        length: 
            min: 1
            max: 150
            message: Please enter an email address between 1 and 150 characters.

        email: 
            message : That does not appear to be a valid email address.

message: 
    validators: 
        required: 
            message: Please enter a message

依赖项

安装

使用Composer安装

  1. 如果您还没有安装,请安装Composer -最好全局安装。
  2. 需要Fortress,可以通过运行以下命令获取:php composer.phar require alexweissman/fortress,或者创建一个composer.json文件
{
    "require": {
        "php": ">=5.6.0",
        "userfrosting/fortress": "^4.1.0"
    }
}

然后运行composer install

  1. vendor/autoload.php文件包含到您的项目中
require dirname(__DIR__) . '/vendor/autoload.php';

用法

请求架构

要读取YAML或JSON架构,请使用YamlFileLoader

$loader = new \UserFrosting\Support\Repository\Loader\YamlFileLoader('schema/forms/contact.yaml');

使用它,它必须被读取并加载到RequestSchemaRepository对象中

$schema = new \UserFrosting\Fortress\RequestSchema\RequestSchemaRepository($loader->load());

如果您愿意,可以在运行时向架构添加额外的验证规则

$schema->addValidator("puppies", "required");

$schema->addValidator("minions", "range", [
    "min" => 0,
    "max" => 20,
    "message" => "Not enough minions"
]);

$schema->addValidator("email", "length", [
    "min" => 1,
    "max" => 100,
    "message" => "ACCOUNT_EMAIL_CHAR_LIMIT"
]);

数据转换

数据转换器执行以下任务

  1. 对输入数组进行白名单检查以符合架构。默认情况下,架构中未列出的任何参数将被过滤掉。其他选项有"error"和"skip"。
  2. 对输入数据执行一系列转换。例如,trimpurify
  3. 为架构中不包含在输入数组中的字段设置默认值。
$post = [
    "puppies" => "<script>I'm definitely really a puppy  </script>0  ",
    "horses" => "seven pretty horses"
];

$transformer = new \UserFrosting\Fortress\RequestDataTransformer($schema);

// Transform, and print transformed data for demo purposes
$transformedData = $transformer->transform($post, "skip");

echo "<h2>Transformed data</h2>";
echo "<pre>";
print_r($transformedData);
echo "</pre>";

服务器端数据验证

要处理用户输入的数组,请使用架构和一个翻译器对象创建一个ServerSideValidator对象。

翻译器对象

Fortress需要一个MessageTranslator对象(参见i18n)来翻译可能出现在规则中的消息键。

$localeLoader = new \UserFrosting\Support\Loader\ArrayFileLoader('locales/en_US/translations.php');
$translator = new \UserFrosting\I18n\MessageTranslator($localeLoader->load());

然后,对输入数组调用validate。如果任何规则失败,validate将返回false。调用errors以获取生成的错误消息列表。您可能希望将这些错误消息存储到闪存消息系统中,以便用户可以显示这些消息。

$validator = new \UserFrosting\Fortress\ServerSideValidator($schema, $translator);

if (!$validator->validate($transformedData)) {
    echo "<h2>Validation results</h2>";
    echo "<pre>";
    print_r($validator->errors());
    echo "</pre>";
}

客户端数据验证

当生成页面或表单时,您将使用一个Adapter类来从您的WDVSS架构生成一组兼容的规则

// Test client validators
$clientVal = new \UserFrosting\Fortress\Adapter\JqueryValidationAdapter($schema, $translator);
echo "<h2>Client-side validation schema (JSON)</h2>";
echo "<pre>";
print_r($clientVal->rules());
echo "</pre>";

消息键

规则的message可以是纯字符串,也可以是可翻译的消息键

在可翻译消息键的定义中,关键字"self"被保留,用于引用正在验证的字段的名称。因此,这样的消息

"MIN_LENGTH" => "The field '{{self}}' must be at least {{min}} characters long"

对于定义为

tagline:
  validators:
    length:
      min: 10
      message: MIN_LENGTH

的字段

将翻译为

"The field 'tagline' must be at least 10 characters long"

仅将规则限制在服务器端或客户端

有时,您可能只想在服务器端应用验证规则,而不是在客户端的JavaScript上,或者反之亦然。例如,可能有一些包含需要服务器端验证但不在浏览器中直接操作的用户隐藏数据的表单。因此,这些字段不需要客户端验证规则。

为此,每个验证规则现在都可以接受一个domain属性。设置为"server"将使其仅在服务器端应用。设置为"client"将使其仅在客户端规则中出现。如果未指定,则默认情况下,规则将在服务器端和客户端应用。您也可以显式设置为值"both"。

测试

phpunit --bootstrap tests/bootstrap.php tests