案例
似乎来自Spoofchecker
扩展的Intl
会产生误报:
<?php // 7.0 on linux
// File encoding of this script is UTF-8 (thus without BOM)
$sDefaultLocale = (new \Locale)->getDefault();
$oSpoofchecker = new \Spoofchecker;
$oSpoofchecker->setAllowedLocales($sDefaultLocale);
$sText = 'abc'; // US-ASCII
header('Content-Type: text/plain');
print
'Default locale: ' . $sDefaultLocale . PHP_EOL
. 'Byte length: ' . strlen($sText) . PHP_EOL // US-ASCII check
. 'Text "' . $sText . '" '
. ($oSpoofchecker->isSuspicious($sText, $sError) ? 'IS' : 'IS NOT')
. ' suspicious' . PHP_EOL
. 'Spoofchecker internal error information:' . PHP_EOL;
var_dump($sError);
结果
Default locale: en_US_POSIX
Byte length: 3
Text "abc" IS suspicious
Spoofchecker internal error information:
NULL
预期结果
Text "abc" IS NOT suspicious
这是因为abc是US-ASCII, suppmably 应该是en_US_POSIX
的默认值。另外PHP Spoofchecker class提到如果使用任何非英文字符,则Spoofchecker::isSuspicious()
的返回码将为TRUE
,而这不是这种情况。
可能的原因
documentation of Spoofchecker::setAllowedLocales()
目前接近于不存在,参数列表不包含可能值的列表。只能假设它必须与Locale
的那个兼容。文档内容如下:
使用RFC 4646语言标记(使用连字符,而不是下划线)标识语言环境
与测试结果相矛盾,其中Locale
使用下划线表示默认语言环境而不是连字符。但是当使用$oSpoofchecker->setAllowedLocales('en-US');
运行另一个测试时,结果保持不变。
问题
如何正确使用Spoofchecker::isSuspicious()
?
答案 0 :(得分:2)
PHP的Intl扩展只是ICU的包装,其中Spoofchecker从ICU版本58开始减少了误报。
来自bug tracker:
ICU 58反映了最新的Unicode更新,该更新弃用了 全脚本可混淆(WSC)检查和混合脚本可混淆 (MSC)检查,可在 http://www.unicode.org/L2/L2016/16229-revising-uts-39-algorithm.pdf
根据ICU 57,支票(WSC和MSC)存在以下缺陷:
- 他们没有将自己限制为指定的字符集 SpoofChecker#setAllowedChars或SpoofChecker#setAllowedLocales。
- 他们没有正确处理包含多个骨架的混淆因素 字符,如'æ'到'ae'。
- WSC表现出很高的假阳性 速率,特别是随着越来越多的条目被添加到 confusables.txt 强>
- 所有字符串失败的MSC也会失败限制级别。 (你的字符串“goօgle”就是一个例子。)
醇>考虑到这些陷阱, WSC和MSC从ICU 58中删除。
强调我的。 WSC检查是您的字符串failing。 (请注意,它通过ICU版本为58.1及以上,因为该检查已完全删除。)
关于如何正确使用Spoofchecker :: isSuspicious():
printf()
并省略WSC检查Spoofchecker::setChecks()
(涵盖此案例)和MSC检查Spoofchecker::WHOLE_SCRIPT_CONFUSABLE
(同样从最近版本中移除) 。)答案 1 :(得分:1)
您可以使用Spoofchecker::setChecks(int $checks)
指定如何验证字符串。
$checks
常量列在Spoofchecker类documentation中,并由用户in comments描述。
您可以使用SpoofChecker::CHAR_LIMIT
(或多个常量的组合,例如:SpoofChecker::CHAR_LIMIT|Spoofchecker::INVISIBLE
):
CHAR_LIMIT
:检查标识符是否仅包含指定可接受字符集中的字符INVISIBLE
:检查标识符是否存在不可见字符,例如零宽度空格或可能不显示的字符序列,例如多次出现相同的非间距标记。
$sDefaultLocale = (new \Locale)->getDefault();
$oSpoofchecker = new \Spoofchecker;
$oSpoofchecker->setAllowedLocales($sDefaultLocale);
$oSpoofchecker->setChecks(SpoofChecker::CHAR_LIMIT);
$sText = 'abc'; // US-ASCII
header('Content-Type: text/plain');
print
'Default locale: ' . $sDefaultLocale . PHP_EOL
. 'Byte length: ' . strlen($sText) . PHP_EOL // US-ASCII check
. 'Text "' . $sText . '" '
. ($oSpoofchecker->isSuspicious($sText, $sError) ? 'IS' : 'IS NOT')
. ' suspicious' . PHP_EOL
. 'Spoofchecker internal error information:' . PHP_EOL;
var_dump($sError);
输出:
Default locale: en_US_POSIX
Byte length: 3
Text "abc" IS NOT suspicious
Spoofchecker internal error information:
NULL
使用isSuspicious()
documentation中的示例,文本Рaypal.com
(第一个字母来自Cyrylic),返回的方法为:
Text "Рaypal.com" IS suspicious