【问题标题】:Is there a way to filter out offensive words from Jcaptcha?有没有办法从 Jcaptcha 中过滤掉冒犯性的词?
【发布时间】:2011-02-03 02:23:54
【问题描述】:

我们在我的团队正在编写的一个小应用程序中使用 JCaptcha 作为验证码工具。然而,就在开发期间(在一个小团队中 - 我们 4 人),我们遇到了一些用于实际验证码的诅咒词和其他可能令人反感的词。有没有办法过滤掉可能令人反感的词,以免它们呈现给用户?

【问题讨论】:

  • 每个词对某人来说都是“可能冒犯的词”。
  • 验证码的重点是程序无法“读取”它们并找出它是哪个单词。找不到其他验证码来源,我认为您不走运
  • @Holograham 是的,不幸的是,我可能受限于使用 JCaptcha,除非我能找到可以打包的其他工具并允许我们在自己的服务器上进行验证。我们还需要 JCaptcha 支持的国际化和 508 合规性(音频文件)支持。我正在与一个非常严格的架构组打交道(叹气)。我很想使用 re-captcha(我相信,它已经有自己的过滤器来处理这类事情),但架构组已经取消了它。
  • 很抱歉,你们完全疯了,认为这是不可能的。至少有 两种 方法可以满足 OP 的要求。您可以防止 CAPTCHA 生成不需要的单词(这非常容易看到您可以访问 JCaptcha 的源代码)或者您可以散列所有不需要的 f!ck sck* 和 d#ck 词,并将它们的哈希值放在一个集合中,并拒绝将哈希到其中一个的验证码。这是微不足道的,你们评论说“按设计它是不可能的”是真的可怕。
  • @Wizard:至少 ReCaptcha 的要点是,它甚至不知道单词本身的一半(它只有图像!)好吧,我不是 100% 确定,如果 JCaptcha 也是如此。

标签: java captcha


【解决方案1】:

我花时间下载 JCaptcha 并查看源代码。基本上,JCatpcha 的工作原理类似于 除了 ReCaptcha 之外的每一个验证码。因此,您想要的只是微不足道的。

JCaptcha 使用非常简单的 WordGenerator 概念,即和接口:

public interface WordGenerator {
    String getWord(Integer length);
    String getWord(Integer length, Locale locale);
}

让我们忽略本地化。

典型用法是这样的:

WordGenerator words = ...
WordToImage word2image = new SimpleWordToImage();
ImageCaptchaFactory factory = new GimpyFactory(words, word2image);
pixCaptcha = factory.getImageCaptcha();

在他们的单元测试中,我们可以看到,出于测试目的:

    WordGenerator words = new DummyWordGenerator("TESTING");
    WordToImage word2image = new SimpleWordToImage();
    ImageCaptchaFactory factory = new GimpyFactory(words, word2image);
    pixCaptcha = factory.getImageCaptcha();

请注意,我们对所使用的“WordGenerator”拥有ENTIRE控制权。

这是我刚刚写的一个(工作的、功能齐全的)单词生成器:

private static final Random r = new Random( System.currentTimeMillis() );

public String getWord( final Integer length ) {
    final StringBuilder sb = new StringBuilder();
    for (int i = 0; i < length; i++) {
        final int rnd = r.nextInt( 52 );
        final char c = (char) (rnd < 26 ? 'a' + rnd : 'A' + (rnd-26));
        sb.append( c );
    }
    return sb.toString();
}

它会生成像这样的随机“单词”:

fqXVxId
cdVWBSZ
zXeJFaY
aeoSeEb
OuBfzvL
unYewjG
EhbzRup
GkXkTyQ
yDGnHmh
mRFgHWM
FFBkTLF
DvCHIIT
fDmjqLH
XMWSOpa
muukLLN
jUedgYK
FlbWARe
WohMMgZ
lmeLHau
djHRqlc

请注意,如果您更喜欢“真实单词”(例如 reCaptcha,但 reCaptcha 将真实单词用于其他目的——因为它有助于扫描/OCRing 书籍!)这不是问题,只需更改 getWord(. ..) 从字典中随机挑选单词。

现在你如何防止侮辱性词语被拾起?这是微不足道的。这里我只举一个例子(请不要争论代码,它真的只是一个的例子来说明它是如何完成的):

private static final Set<String> s = new HashSet<String>();

static {
    s.add( "f**k" );
    s.add( "suck" );
    s.add( "dick" );
}

private static final Random r = new Random( System.currentTimeMillis() );

public String getWord( Integer length ) {
    String cand = getRandomWord( length );
    while ( isSwearWord(cand) ) {
        cand = getRandomWord( length );
    }
    return cand;
}

private boolean isSwearWord( final String w ) {
    return s.contains( w.toLowerCase() );
}

public String getRandomWord( final Integer length ) {
    final StringBuilder sb = new StringBuilder();
    for (int i = 0; i < length; i++) {
        final int rnd = r.nextInt( 52 );
        final char c = (char) (rnd < 26 ? 'a' + rnd : 'A' + (rnd-26));
        sb.append( c );
    }
    return sb.toString();
}

现在如果你想阻止脏话,你可能想要阻止那些接近脏话的词(例如“fvck”“dikk” 等)。这又是微不足道的:

 private boolean isSwearWord( final String w ) {
    List<String> ls = generateAllPermutationsWithLevenhsteinEditDistanceOne(w);
    for ( final String cand : ls ) {
        if ( s.contains( cand.toLowerCase()) ) {
            return true;
        }
    }
    return false;
}

“generateAllPermutationsWithLevenhsteinEditDistanceOne(w)”方法的编写留给读者作为练习。

【讨论】:

  • @chris_l:您的问题在于您没有意识到在安全方面存在不对称性:“被告”比攻击者拥有更多可用信息。你的整个胡言乱语完全与有人会说“PKCS 不起作用,因为你不能乘以两个巨大的素数,因为你不能分解两个巨大的素数”我>。这是一个完全循环的论点,准确地忽略了 PKCS 为何有效以及 Captcha 为何有效的全部要点。 必须有一种方法可以验证答案是否正确(或不正确)。我们在服务器上有单词信息。
  • 顺便说一句,生成所有列文斯坦编辑距离为 1 的排列比计算编辑距离本身更容易。
  • 感谢@WizardOfOdds - 这是我希望描述如何做的事情,但您提供了非常详细的答案。
  • @elduff:我决定删除另一篇文章中的火焰战。我同意,Wizard 很好地回答了你的问题 (+1)。
猜你喜欢
  • 2022-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-07
  • 1970-01-01
  • 2015-05-08
  • 2022-12-08
  • 2013-08-30
相关资源
最近更新 更多