坏词 - 阻止用户绕过php中的坏词过滤器

时间:2018-02-16 18:24:10

标签: php regex

我使用badwordfilter数组来防止用户生成内容中的坏词。

坏词的例子:

$badwords = array ( 1 => 'adult', 2 => 'porn' )

问题:

用户总是试图避免使用点,逗号或其他类似* *的字符过滤器!#

示例:

a.dult
po,rn

无论如何可能,检查字符串/坏词是否有字符列表(。,?!),如果找到一个字,其中一个字符在里面,给出错误信息?

"Don´t bypass the badword filter".

非常感谢你的时间。

我知道有很多方法可以绕过一个badword过滤器,但它足以检查一个字符串,看看里面有一个点或逗号的单词。

3 个答案:

答案 0 :(得分:0)

如果您在MySQL中有一个表,其中包含已排除的单词列表,您可以运行如下查询:

bind_rows(
  esoph %>% .[rep(seq_len(nrow(.)), .$ncases), 1:3] %>% mutate(case=1),
  esoph %>% .[rep(seq_len(nrow(.)), .$ncontrols), 1:3] %>% mutate(case=0)
) %>%
summarise_marginal(
  vars(highage = agegp %in% c('65-74','75+'),
       highalc = alcgp %in% c('80-119','120+'),
       hightob = tobgp %in% c('20-29','30+'),
       highrisk = highage & highalc & hightob,
       all = 1),
  n=length(agegp),
  ncases=sum(case),
  case.rate=mean(case),
  .removeF=TRUE
)

#> # A tibble: 5 x 5
#>      group value     n ncases case.rate
#>      <chr> <chr> <int>  <dbl>     <dbl>
#> 1  highage  TRUE   273     68 0.2490842
#> 2  highalc  TRUE   301     96 0.3189369
#> 3  hightob  TRUE   278     64 0.2302158
#> 4 highrisk  TRUE    11      5 0.4545455
#> 5      all     1  1175    200 0.1702128

这将返回一个排除的单词列表及其计数。

我所说的处理可以简单如下:

SELECT word, COUNT(word) AS matches 
FROM badwords 
WHERE LOWER('User input string goes here after processing') LIKE CONCAT('%', word, '%') 
GROUP BY word

删除所有特殊字符,或者您可以尝试将字符替换为预期的替换字符,例如o代表0等。这是对使用ASCII创造性的人的替代复杂性战争。不是真正可以赢得的战争,但你可以减轻常见的选择。

答案 1 :(得分:0)

正则表达式\b(badword)\b[.,?!]

详细说明:

  • \b在字边界处断言位置
  • []匹配列表中的单个字符

PHP代码

$str = 'bla bla p.orn, bla bla a.dult bla bla association';

$bad_words = array('adult', 'porn', 'ass');
$reg = '~\b' . implode('\b|\b', $bad_words) . '\b~';

preg_match_all($reg, preg_replace('~[.,?!]~', '', $str), $matches);

if(count($matches[0]) > 0)
    echo '"Don´t bypass the badword filter".';

输出:

Array
(
    [0] => porn
    [1] => adult
)

Code demo

答案 2 :(得分:0)

您可以使用Levenshtein distance

构建一个函数
<?php

$data = 'bla bla p.orn, bla bla a.dult bla bla association';

function filter($string) {
    $badwords = array('adult', 'porn', 'ass');
    $words = array_unique(preg_split("~\s+~", $string));
    foreach ($words as $word) {
        foreach ($badwords as $bad) {
            if (levenshtein($word, $bad) <= 1) {
                return ["result" => false, "word" => $word];
            }
        }
    }
    return ["result" => true, "word" => null];
}

$f = filter($data);
if ($f["result"] === false) {
    echo "Please don't use {$f["word"]}\n";
}
?>

这会拆分&#34;字&#34; (一个单词被认为是由空格分隔)并计算到坏单词列表中每个单词的距离 这是迄今为止最快的方法,但认为pornp0rnp$rn相同。距离0基本上是同一个单词,在这里你肯定需要一些调整。