服务器端验证
简介
Joomla提供了一个框架,用于实现客户端和服务器端的验证。
客户端验证是在浏览器中使用JavaScript执行的,JavaScript与网页一起下载。
服务器端验证是在HTTP POST请求发送表单字段时,在服务器上的PHP中执行。
其中,服务器端验证更为重要,因为黑客可以使用curl等工具直接向您的Web服务器发送HTTP POST请求,从而绕过您的HTML表单及其客户端验证。
本节概述了Joomla中的服务器端验证:以下内容描述了客户端验证。
服务器端验证
这是通过在表单定义中指定validate=...
属性触发的。在前面各节中使用的示例表单中,电话号码字段存在验证
<field name="telephone"
type="telephone"
label="Enter telephone number"
required="true"
size="40"
class="inputbox"
validate="tel" />
validate="tel"
行触发此字段上的验证,它将使用libraries/src/Form/Rule中的TelRule中的test
函数检查字段值是否有效。
您可以通过查看libraries/src/Form/Rule目录中的类文件来查看Joomla提供的验证规则列表,并选择要对表单中的字段运行的验证例程。例如,要使用EmailRule,您需要在表单定义中的电子邮件字段中包含validate="email"
。
自定义服务器端验证
您可以通过编写自定义验证规则来定义字段的自定义验证。
com_exampleform示例组件(可从这里下载)提供了另一个服务器端验证的工作示例。
在本节中,我们将以一个名为“custom”的自定义规则为例,我们将使用它来替换Joomla提供的电话号码验证。您当然可以根据需要命名自己的规则。然后您需要执行3件事
- 在字段定义中,针对该字段添加属性
validate="custom"
- 编写您的CustomRule.php文件 - 我们很快就会讲到它
- 通过
addruleprefix
属性告诉Joomla在哪里可以找到您的CustomRule类
假设您的com_example
组件在您的XML清单文件中定义了
<namespace path="src">Mycompany\Component\Example</namespace>
并且您决定将您的规则存储在管理员区域中的src/Rule/CustomRule.php中,那么您将拥有
<field
addruleprefix="Mycompany\Component\Example\Administrator\Rule"
name="telephone"
type="telephone"
label="Enter telephone number"
required="true"
size="40"
class="inputbox"
validate="custom"
message="The telephone number field is wrong" />
并在您的CustomRule.php内部
namespace Mycompany\Component\Example\Administrator\Rule;
class CustomRule …
如果您可以将自定义验证规则指定为正则表达式,那么最简单的选择是重用Joomla FormRule类,该类使用受保护的变量$regex
验证值
namespace Mycompany\Component\Example\Administrator\Rule;
use Joomla\CMS\Form\FormRule;
class CustomRule extends FormRule
{
protected $regex = '^[0-9\*\#]+$';
}
然后,Joomla FormRule将根据覆盖的$regex
值验证字段,在本例中,检查电话号码是否仅包含字符0到9、*和#。
如果您的验证不能表示为正则表达式,那么您将必须自己提供test
函数,遵循libraries/src/Form/Rule中其他验证规则的示例
/**
* Method to test the range for a number value using min and max attributes.
*
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
* @param Registry $input An optional Registry object with the entire data set to validate against the entire form.
* @param Form $form The form object for which the field is being tested.
*/
public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) { … }
从注释中可以看出,您被传递了很多信息,以防您的验证例程需要访问它!例如,Joomla NumberRule测试值是否在XML表单中字段定义中设置的“min”和“max”属性之间,它从$element
参数中获取这些限制。同样,您可以在字段定义中指定自己的属性,从$element
参数中提取它们,并在对用户输入的值进行验证时使用它们。您只需要从test
函数返回true
或false
即可。
其他验证
除了针对字段的任何指定验证外,Joomla还将对数据执行两次检查
- 如果设置了属性
required
,则它将验证是否已输入值 - 如果设置了属性
disabled
,则它将验证是否未输入值(默认值除外)
验证错误消息
默认情况下,当字段验证失败时,Joomla会输出“无效字段”错误消息。要使Joomla输出自定义消息,您可以将message="错误的电话号码"
属性包含到字段属性中,就像在本页前面电话字段定义中所做的那样。
由于字段属性包含在传递给验证test
函数的XML元素中,因此您可以从test
方法设置此属性。以下是电话号码验证规则的示例。
<?php
namespace Mycompany\Component\SampleForm2\Site\Rule;
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Form\FormRule;
use Joomla\Registry\Registry;
use Joomla\CMS\Form\Form;
class TelephoneRule extends FormRule
{
protected $regex = '^[0-9\#\*]+$'; // just numbers plus * plus #
public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null)
{
if (preg_match(\chr(1) . $this->regex . \chr(1) . $this->modifiers, $value)) {
return true;
}
$attr = $element->attributes();
$error_message = 'The telephone number ' . $value . ' is wrong';
// how you write the message attribute to the XML element depends on whether it's already set
if (isset($attr['message'])) {
$element->attributes()->message = $error_message;
} else {
$element->addAttribute('message', $error_message);
}
return false;
}
}