Java验证码库的推荐

68

我正在寻找替代JCaptcha的技术,因为它似乎已不再维护,并且一开始就不是很好。新技术需要与JavaEE Web应用程序良好集成。

在我看来,有三个选择:

  • JCaptcha - 不再维护,API较为粗糙
  • SimpleCaptcha - API更好,验证码更美观,但似乎仅支持Java6
  • ReCaptcha - 使用简单,使用远程Web服务生成验证码,但外观上没有太多控制

是否有其他人使用过其他技术,并推荐使用?


当我在探索其他验证码库时,我发现了http://captcha.com/doc/java/captcha-for-java.html,也许它可以帮助一些人! - Adelin
这里有一个不错的离线验证码实现:http://javalite.io/captcha。你只需要一个类:https://github.com/javalite/activeweb/blob/master/activeweb/src/main/java/org/javalite/activeweb/Captcha.java - Dherik
6个回答

73

我是SimpleCaptcha的作者。尽管出于人道主义考虑,我建议你尽可能使用ReCaptcha,但出于某些组织禁止使用ReCaptcha这样的库的政策,我提供了SimpleCaptcha。SimpleCaptcha旨在完全独立,没有外部依赖:只要您在J2EE容器中,就应该没问题。

此外,SimpleCaptcha现已提供Java 1.5或Java 6版本。


1
SimpleCaptcha到底有哪些依赖关系?我正在使用Tomcat 7,每当我将GimpyRenderer添加到我的验证码中时,就会出现java.lang.VerifyError,这太糟糕了,因为我更喜欢SimpleCaptcha的API而不是Kaptcha的。 - spaaarky21
2
你的解决方案很好,但我最后得到它的Maven仓库(http://repo.enonic.com/maven)已经无法访问了,没有其他位置可以获取... 我会把一个jar文件放到我的git中,但是在maven中获取它会更好。 - sab
@jchilders 我需要将SimpleCaptcha用作osgi bundle。这就是为什么我尝试将其构建为maven项目的原因。为此,我需要jhlabs,但我从http://www.jhlabs.com/ip/filters/download.html下载的源代码版本不兼容。你能告诉我你使用的jhlabs版本吗? - user2022068
1
而且,你能否将你的项目提供给构建和作为Maven项目。我看到很多人都需要它。 - user2022068

26

ReCaptcha是唯一应该使用的验证码,因为它是唯一一个通过几乎无限的数据库来使世界变得更好的验证码(改善对旧文本的OCR结果)。

所有其他验证码通常都受其数据库限制,或者对这个世界没有任何好处。

编辑:我找到了使用reCAPTCHA实现验证码的步骤。

您可以在此处检查使用Java的在线和离线验证码。


24
好的,但是造福人类并不在我的优先事项列表中 :) 另外,JCaptcha和SimpleCaptcha生成随机验证码,因此数据库大小不是问题。 - skaffman
3
还有一件事——许多带有彩色/旋转背景/线条/图像的验证码,对大多数用户来说过于复杂(例如著名的 rapidshare 猫数字验证码)。 相反,reCAPTCHA 基于真实的英文单词,因此对大多数人来说更容易。你不会希望应用一个让 90% 的人都会发送邮件告诉你“我无法通过验证码”的验证码。 - Francis
6
我质疑随机验证码比数据库支持的验证码更容易受到攻击的说法。关于 ReCaptcha,它的一个好处是它向用户呈现的是一个高质量 OCR 实现已经失败了的单词。 - Lawrence Dol
7
reCAPTCHA对许多人来说太难了,经常出现无法辨认的情况。 - OlegYch
3
我想知道 reCaptcha 的人性化好处是否会传递到中国大陆那些被伟大的防火墙隔绝的人们手中。 :) https://dev59.com/k2Ag5IYBdhLWcg3wSpPD - Hoang Tran
显示剩余4条评论

21
当 ReCaptcha 出现故障或不可用时会发生什么?您的服务是否会直接停止运行?当 ReCaptcha 出现故障时,您是否会停止注册用户?即使 ReCaptcha 没有运行,您是否允许用户注册?如果是这样,那么这会带来什么安全风险?特别是如果您在更多地方使用 CAPTCHA,例如重置密码表单、登录表单等,在没有 CAPTCHA 组件的情况下使用将是不可接受的。
Java 的 CAPTCHA 技术现状比较糟糕,对于那些不能接受托管服务的人来说,SimpleCaptcha 似乎是最好的解决方案。

3
你真的认为你的服务比ReCaptcha更稳定,尤其是在谷歌收购了它之后吗?即使Facebook也在使用ReCaptcha,所以除非你的服务比Facebook更大,不然不用担心……我仍然认为没有比ReCaptcha更好的验证码系统。 - Francis
7
谷歌之前曾多次出现过宕机(不仅仅是Gmail,搜索也有)。如果你拥有自己的服务,而且只被你使用,那么当你的验证码出现问题时,你就可以放心地说你的整个系统都崩溃了。我很想知道脸书在宕机事件中会怎么做 - 他们必须一直忍耐直到修复吗?他们有备份计划吗?宕机对他们来说是否真的那么重要?如果你提供的服务比查看谁戳了你更重要,或者你有服务等级协议要求,那么解决方案并不像“只需等待”这么简单。 - Mike
3
当CEO敲门询问为什么他们忘记密码后无法重置密码,或者无法将最新的大客户添加到系统中时,“不是通常关键的”就不够用了。这取决于你的服务所提供的内容以及其SLA要求。“不是通常关键的”是一个关于SLA的问题,不应该被完全驳回。 - Mike
4
自从我发布这篇文章以来,我们遇到了2次reCAPTCHA失败。一次是在URL更改时(https://groups.google.com/forum/?fromgroups#!topic/recaptcha/V7qswqBnA1o),另一次是IP地址更改时(https://groups.google.com/forum/?fromgroups#!topic/recaptcha/_Lg_MHsGKLw)。是的,两次都有高层管理者找上门来,想知道为什么他们不能登录。如果我们有一个自托管的解决方案,那么只有在目标系统也宕机时,验证码才会出现问题。 - Mike
1
@Makky,你打算如何在不使用DNS的情况下访问由谷歌控制的服务器? - fabspro
显示剩余7条评论

11

在reCAPTCHA如今变得如此流行之前,我创建了http://kaptcha.googlecode.com。它还提供了自主托管的功能,在某些情况下可能是必要的。

Kaptcha是SimpleCaptcha的大幅修改和更新版本,并支持JDK5/6。


你好,Jon Stevens,我不确定为什么在谷歌应用引擎上无法使用Kaptcha。谢谢, Xuwei - user341827
这是 com.google.code.kaptcha:kaptcha:jar 吗?我们的应用程序中有 ${basedir}/src/main/webapp/WEB-INF/lib/kaptcha-2.3.2.jar,但我想用来自 Maven 中央仓库的版本来替换它。但是我在那里只能找到 com.github.penggle:kaptcha 2.3.3 版本。这是同一个吗? - Amedee Van Gasse
好问题,我的看法是这是Maven设计的巨大失败。你从Maven中央下载的东西可能来自任何地方,所以...谁知道呢。我猜答案是否定的。我是原作者,可以在此找到从Google代码导出的项目:https://github.com/lookfirst/kaptcha 我还发现了这个克隆版本,其中包括添加了一个pom的一些更改:https://github.com/axet/kaptcha - Public Profile
我比较了源代码,它们是一样的 - 但正如你所说,没有完全的保证源代码对应于jar文件。不过我试过了,它似乎按预期工作。请注意风险。 - Amedee Van Gasse

5

SimpleCaptcha非常好用且易于使用。

以下是一个JSF 2.0结合SimpleCaptcha的示例(主页上有一个JSP示例)。

请注意,我甚至不需要在bean中存储验证码值,仅需验证即可。

该bean:

// imports missing here

@ManagedBean
@SessionScoped
public class LoginBean implements Serializable
{
    public void validateCaptcha(FacesContext context,
                                UIComponent componentToValidate,
                                Object value)
            throws ValidatorException
    {
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        Captcha secretcaptcha = (Captcha) session.getAttribute(Captcha.NAME);
        if (secretcaptcha.isCorrect(value.toString()))
            return;

        // optional: clear field
        ((HtmlInputText) componentToValidate).setSubmittedValue("");

        throw new ValidatorException(new FacesMessage("Captcha does not match"));
    }
}

相关的Facelet代码段:

<h:form id="CaptchaForm">
    Type this: <br/>
    <h:graphicImage id="CaptchaImgID" value="/simpleCaptcha.png"/> <br/>
    <h:inputText id="CaptchaID"
                 required="true"
                 requiredMessage="Captcha missing"
                 validator="#{loginBean.validateCaptcha}"
                 validatorMessage="Captcha does not match"
                 immediate="true">
    </h:inputText>
    <br/>
    <h:commandButton value="Check"/>

    <p/>
    <!-- message for the input field -->
    <h:message id="CaptchaMsgID" for="CaptchaID" style="color:red" />
</h:form>

web.xml文件中相关的部分:

<servlet>
    <servlet-name>SimpleCaptcha</servlet-name>
    <servlet-class>nl.captcha.servlet.SimpleCaptchaServlet</servlet-class>
    <init-param>
        <param-name>captcha-width</param-name>
        <param-value>250</param-value>
    </init-param>
    <init-param>
        <param-name>captcha-height</param-name>
        <param-value>75</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>SimpleCaptcha</servlet-name>
    <url-pattern>/simpleCaptcha.png</url-pattern>
</servlet-mapping>

祝您愉快 :-)


这里可能存在一个缺陷:如果我只请求一次验证码图像,然后再也不请求验证码图像,而是始终使用其中的文本,会怎样?simplecaptcha是否有类似于captcha.invalidate_currentimage的功能? - nosam
我不理解这个问题,你的“just use the text from it always”是什么意思?由于头文件的原因,该图像未被缓存,因此浏览器每次显示JSF页面时都会重新请求它。http://sourceforge.net/tracker/?func=detail&aid=1546896&group_id=147810&atid=769555 - Tilman Hausherr

3

Kaptcha是一个很好的替代方案,如果您想要托管自己的验证码服务而不是依赖于第三方验证码服务(如Recaptcha)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接