与reCAPTCHA的Spring集成

有时我们只需要CAPTCHA ,这是一个可悲的事实。 今天,我们将学习如何与reCAPTCHA集成。 因为主题本身并不是特别有趣和高级,所以我们将通过使用Spring Integration处理低级细节来过度设计(?)。 Google决定使用reCAPTCHA的决定取决于两个因素:(1)这是一种适度良好的CAPTCHA实施方案,具有体面的图像,并内置了对视力障碍者的支持;(2)外包CAPTCHA可使我们在服务器端保持无状态。 更不用说我们在图书数字化方面有所帮助。
第二个原因实际上很重要。 通常,您必须在服务器端生成CAPTCHA,并将预期结果存储在例如用户会话中。 当响应返回时,您比较预期的并输入了CAPTCHA解决方案。 有时我们不想在服务器端存储任何状态,更不用说实现验证码并不是特别有意义的任务。 因此,拥有现成的和可以接受的东西真是太好了。
完整的源代码一如既往地可用,我们从一个简单的Spring MVC Web应用程序开始,没有任何验证码。 reCAPTCHA是免费的,但需要注册,因此第一步是在我们的示例项目中唱歌并生成您的公钥/私钥和填写的app.properties配置文件。
要在表单上显示reCAPTCHA并将其包括在表单中,只需添加JavaScript库:
<div id="recaptcha"> </div>
...
<script src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
并将reCAPTCHA小部件放置在您喜欢的任何位置:
Recaptcha.create("${recaptcha_public_key}","recaptcha",{theme: "white",lang : 'en'}
);
官方文档非常简洁,描述性强,因此我不会深入探讨这一细节。 当您在<form/>包含此小部件时,当用户提交时,您将收到两个额外的字段: recaptcha_response_fieldrecaptcha_challenge_field 。 第一个是用户键入的实际文本,第二个是每个请求生成的隐藏令牌。 reCAPTCHA服务器可能会将它用作会话密钥,但是我们不在乎,我们要做的就是将此字段进一步传递给reCAPTCHA服务器 。 我将使用HttpClient 4对外部服务器执行HTTP请求,并在Scala中执行一些巧妙的模式匹配来解析响应:
trait ReCaptchaVerifier {def validate(reCaptchaRequest: ReCaptchaSecured): Boolean}@Service
class HttpClientReCaptchaVerifier @Autowired()(httpClient: HttpClient,servletRequest: HttpServletRequest,@Value("${recaptcha_url}") recaptchaUrl: String,@Value("${recaptcha_private_key}") recaptchaPrivateKey: String) extends ReCaptchaVerifier {def validate(reCaptchaRequest: ReCaptchaSecured): Boolean = {val post = new HttpPost(recaptchaUrl)post.setEntity(new UrlEncodedFormEntity(List(new BasicNameValuePair("privatekey", recaptchaPrivateKey),new BasicNameValuePair("remoteip", servletRequest.getRemoteAddr),new BasicNameValuePair("challenge", reCaptchaRequest.recaptchaChallenge),new BasicNameValuePair("response", reCaptchaRequest.recaptchaResponse))))val response = httpClient.execute(post)isReCaptchaSuccess(response.getEntity.getContent)}private def isReCaptchaSuccess(response: InputStream) = {val responseLines = Option(response) map {Source.fromInputStream(_).getLines().toList} getOrElse NilresponseLines match {case "true" :: _ => truecase "false" :: "incorrect-captcha-sol" :: _=> falsecase "false" :: msg :: _ => throw new ReCaptchaException(msg)case resp => throw new ReCaptchaException("Unrecognized response: " + resp.toList)}}}class ReCaptchaException(msg: String) extends RuntimeException(msg)
唯一缺少的部分是ReCaptchaSecured特性,它封装了前面提到的两个reCAPTCHA字段。 为了使用reCAPTCHA保护任何Web表单,我只是在扩展此模型:
trait ReCaptchaSecured {@BeanProperty var recaptchaChallenge = ""@BeanProperty var recaptchaResponse = ""
}class NewComment extends ReCaptchaSecured {@BeanProperty var name = ""@BeanProperty var contents = ""
}
整个CommentsController.scala并不相关。 但是结果是!
这样就可以了,但是显然不是很壮观。 您如何用Spring Integration替换低级HttpClient调用? ReCaptchaVerifier接口(特征)保持不变,因此不必更改客户端代码。 但是我们将HttpClientReCaptchaVerifier重构为两个单独的,较小的,相对高级的抽象类:
@Service
class ReCaptchaFormToHttpRequest @Autowired() (servletRequest: HttpServletRequest, @Value("${recaptcha_private_key}") recaptchaPrivateKey: String) {def transform(form: ReCaptchaSecured) = Map("privatekey" -> recaptchaPrivateKey,"remoteip" -> servletRequest.getRemoteAddr,"challenge" -> form.recaptchaChallenge,"response" -> form.recaptchaResponse).asJava}@Service
class ReCaptchaServerResponseToResult {def transform(response: String) = {val responseLines = response.split('\n').toListresponseLines match {case "true" :: _ => truecase "false" :: "incorrect-captcha-sol" :: _=> falsecase "false" :: msg :: _ => throw new ReCaptchaException(msg)case resp => throw new ReCaptchaException("Unrecognized response: " + resp.toList)}}}
请注意,我们不再需要实现ReCaptchaVerifier ,Spring Integration将为我们做到这一点。 我们只需要告诉我们框架应该如何使用上面提取的构建块。 我想我还没有描述Spring Integration是什么以及它是如何工作的。 简而言之,它是企业集成模式的非常纯净的实现(有人可能将其称为ESB)。 消息流是使用XML描述的,可以嵌入到标准Spring XML配置中:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/integration"xmlns:http="http://www.springframework.org/schema/integration/http"xsi:schemaLocation="http://www.springframework.org/schema/integrationhttp://www.springframework.org/schema/integration/spring-integration.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/integration/httphttp://www.springframework.org/schema/integration/http/spring-integration-http.xsd"><!-- configuration here -->    </beans:beans>
在我们的案例中,我们将描述从HttpClientReCaptchaVerifier Java接口/ Scala特征到reCAPTCHA服务器再返回的消息流。 在必须将ReCaptchaSecured对象转换为HTTP请求并将HTTP响应转换为有意义的结果的方式上,该方法从接口透明返回。
<gateway id="ReCaptchaVerifier" service-interface="com.blogspot.nurkiewicz.recaptcha.ReCaptchaVerifier" default-request-channel="reCaptchaSecuredForm"/><channel id="reCaptchaSecuredForm" datatype="com.blogspot.nurkiewicz.web.ReCaptchaSecured"/><transformer input-channel="reCaptchaSecuredForm" output-channel="reCaptchaGoogleServerRequest" ref="reCaptchaFormToHttpRequest"/><channel id="reCaptchaGoogleServerRequest" datatype="java.util.Map"/><http:outbound-gatewayrequest-channel="reCaptchaGoogleServerRequest"reply-channel="reCaptchaGoogleServerResponse"url="${recaptcha_url}"http-method="POST"extract-request-payload="true"expected-response-type="java.lang.String"/><channel id="reCaptchaGoogleServerResponse" datatype="java.lang.String"/><transformer input-channel="reCaptchaGoogleServerResponse" ref="reCaptchaServerResponseToResult"/>
尽管有大量的XML,但是整个消息流还是非常简单的。 首先我们定义网关 ,它是Java接口和Spring Integration消息流之间的桥梁。 ReCaptchaVerifier.validate()的参数稍后变成一条消息 ,该消息发送到reCaptchaSecuredForm channel 。 ReCaptchaSecured对象从该通道传递到ReCaptchaFormToHttpRequest 转换器 。 转换器的用途是从ReCaptchaSecured对象到Java映射的两次转换,代表一组键值对。 稍后,此映射(通过reCaptchaGoogleServerRequest通道)传递到http:outbound-gateway 。 该组件的职责是将先前创建的地图转换为HTTP请求并将其发送到指定的地址。
响应返回时,将其发送到reCaptchaGoogleServerResponse通道。 ReCaptchaServerResponseToResult转换器将采取行动,将HTTP响应转换为业务结果(布尔值)。 最终,转换器结果被路由回网关。 默认情况下,所有操作都是同步发生的,因此我们仍然可以使用简单的Java接口进行reCAPTCHA验证。
信不信由你,这一切正常。 我们不再使用HttpClient (猜测一切都比HttpClient 4 API更好……),而不是一个“巨大”的类,我们有一组较小的,集中的,易于测试的类。 该框架处理接线和底层细节。 精彩?
建筑师的梦想还是开发商的噩梦?
让我通过引用以上介绍的结论来总结我们的努力:在架构利益与开发有效性之间取得平衡 。 Spring Integration能够从各种异构源(如JMS,关系数据库甚至FTP)接收数据,以多种方式聚合,拆分,解析和过滤消息,最后使用最奇特的协议进一步发送消息。 手工编写所有代码是一项非常繁琐且容易出错的任务。 另一方面,有时我们只是不需要所有的幻想,而弄脏我们的手(例如,通过执行手动HTTP请求并解析响应)则更加简单易懂。 在盲目地将整个体系结构基于非常高级的抽象或基于手工编码的低级过程之前,请考虑一下后果和平衡。 没有解决方案可以解决所有问题。 您发现哪个版本的reCAPTCHA集成更好​​?
参考资料: 使用…与reCAPTCHA集成... Java社区博客上的JCG合作伙伴 Tomasz Nurkiewicz的Spring Integration 。

翻译自: https://www.javacodegeeks.com/2012/05/spring-integration-with-recaptcha.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《机器学习基石》---感知机算法

1 推导感知机模型 基本思想是&#xff0c;把特征的线性加权值作为一个分数&#xff0c;根据这个分数与一个门限值的关系来进行分类&#xff1a; 我们加一个特征x0等于1&#xff0c;门限值就可以放到w里面去&#xff0c;得到更简单的形式&#xff1a; 这就是感知机模型&#xff…

Python之路【第八篇】:堡垒机实例以及数据库操作

Python之路【第八篇】&#xff1a;堡垒机实例以及数据库操作 堡垒机前戏 开发堡垒机之前&#xff0c;先来学习Python的paramiko模块&#xff0c;该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接&#xff1a; 12…

ADF BC:创建绑定到业务组件的UI表

在此示例中&#xff0c;我们将展示如何创建绑定到业务组件的简单UI表&#xff08;af&#xff1a;table&#xff09;。 我再次尝试使用简单的标准在网上进行搜索&#xff1a; “如何创建绑定到业务组件ADF 11g的af&#xff1a;table” 我必须承认我没有得到我想要的答案。 信息…

MyBaits 错误分析

错误原因&#xff1a;在DAO的映射文件中&#xff0c;在映射标签中的type类型写成DAO类了&#xff0c;应该写成javaBean转载于:https://www.cnblogs.com/shuaiandjun/p/5428847.html

斑马打印机linux驱动安装教程,linux-Zebra软件包的基本安装与配置

Zebra是一个路由软件包&#xff0c;提供基于TCP/IP路由服务&#xff0c;支持RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, BGP- 4,和 BGP-4等众多路由协议。Zebra还支持BGP特性路由反射器(Route Reflector)。除了传统的 IPv4路由协议&#xff0c;Zebra也支持IPv6路由协议。如果运行的…

Java 7对抑制异常的支持

在JDK 7中 &#xff0c;向Throwable类&#xff08; Exception和Error类的父类&#xff09;添加了一个新的构造函数和两个新方法。 添加了新的构造函数和两个新方法以支持“抑制的异常”&#xff08;不要与吞咽或忽略异常的不良做法相混淆&#xff09;。 在本文中&#xff0c;我…

易于使用的单位和集成代码

此示例说明如何使用Maven和Sonar生成单元测试和集成测试的覆盖率。 它使用非常简单的技术&#xff0c;只需10-15分钟即可在任何现有的Maven构建中运行。 它可用于单元&#xff0c;集成&#xff0c;ATDD或任何其他类型的测试套件。 覆盖率结果显示在Sonar中。 有什么事吗&#x…

Ubuntu 16.04 安装 VMware-Workstation-12

以前一直使用 Ubuntu Virtaulbox &#xff0c;最近测试了 VMware-Workstation-9,性能超过 Virtaulbox-4.2.x,下面是详细步骤:1 首先准备一个Ubuntu 系统 lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04 LTS Release: 16.04 …

SSH实战 · 唯唯乐购项目(中)

用户模块三&#xff1a;一级分类的查询创建一级分类表并导入基本数据CREATE TABLE category (cid int(11) NOT NULL AUTO_INCREMENT,cname varchar(255) DEFAULT NULL,PRIMARY KEY (cid)) ENGINEInnoDB AUTO_INCREMENT11 DEFAULT CHARSETutf8;建包及相应的类:com.weiwei.shoppi…

Android的IPC机制(一)——AIDL的使用

综述 IPC(interprocess communication)是指进程间通信&#xff0c;也就是在两个进程间进行数据交互。不同的操作系统都有他们自己的一套IPC机制。例如在Linux操作系统中可以通过管道、信号量、消息队列、内存共享、套接字等进行进程间通信。那么在Android系统中我们可以通过Bin…

Netty:透明地使用SPDY和HTTP

大多数人已经从谷歌那里听说过SPDY&#xff0c;该协议被提议作为老化的HTTP协议的替代品。 Web服务器是浏览器正在缓慢地实现该协议&#xff0c;并且支持正在增长。 在最近的文章中&#xff0c;我已经写过SPDY的工作方式以及如何在Jetty中启用SPDY支持。 由于Netty&#xff08;…

selenium 等待页面加载完成

一、隐形加载等待&#xff1a; file:///C:/Users/leixiaoj/Desktop/test.html 该页面负责创建一个div <html> <head><title>Set Timeout</title><style>.red_box {background-color: red; width 20%; height:100px; border: none;}</style&…

linux nfsnobody用户,处理CentOS 5.5 x64 配置NFS服务过程中nfsnobody用户造成的问题

4、我们编译一下这个NFS的配置文件。[rootNFS /]# vi /etc/exports/share 192.168.60.0/24(rw,sync,all_squash,root_squash) (我们允许这个共享对192.168.60.0/24网段可读可写&#xff0c;且将所有访问者包括root的身份都改为nfsnobody)[rootNFS /]# /etc/init.d/nfs resta…

c语言空格有什么作用,空格在c语言中怎么表示 C语言中的空格字符怎么表示

c语言中表示空格的是什么代码&#xff1f;分析如下&#xff1a; 不是所有字符都需要转义的&#xff0c;空格直接就敲空格&#xff0c;或者使用ASCII码值赋值为32。 空格没有转义字符。合法转义字符如下&#xff1a;\a 响铃(BEL) 、\b 退格(BS)、\f 换页(FF)、\n 换行(LF)、\r 回…

StringMVC 中如何做数据校验

步骤一&#xff1a;引入四个jar包 步骤二&#xff1a;注册类型转换器 <context:component-scan base-package"cn.happy.controller"></context:component-scan><!-- 配置验证器 --><bean id"myvalidator" class"org.springframe…

ibm+x3650+m4+linux+raid驱动,IBM X3650M4阵列卡驱动下载

ibm X3650M4raid阵列卡驱动适合安装windowsserver2008,windowsserver2008R2,系统问题&#xff0c;服务器问题&#xff0c;可以联系我们也可以到5分享论坛发帖求助。IBM System x3650 M4服务器是一款应用最为广泛的2U机架服务器&#xff0c;支持Xeon E5-2600机架服务器的所有产品…

UML类图与类的关系详解

在画类图的时候&#xff0c;理清类和类之间的关系是重点。类的关系有泛化(Generalization)、实现&#xff08;Realization&#xff09;、依赖(Dependency)和关联(Association)。其中关联又分为一般关联关系和聚合关系(Aggregation)&#xff0c;合成关系(Composition)。下面我们…

python之路-SQLAlchemy

SQLAchemy SQLAlchemy是Python编程语言下的一款ORM框架&#xff0c;该框架建立在数据库API之上&#xff0c;使用关系对象映射进行数据库操作&#xff0c;简言之便是&#xff1a;将对象转换成SQL&#xff0c;然后使用数据API执行SQL并获取执行结果。 安装&#xff1a; pip3 inst…

Linux中vim编辑器的缩进的功能键

vim编程时,经常需要对代码进行缩进处理,以增加程序的可读性和后期的代码维护. 可以采用多种方式达到缩进的目的: 1) 命令模式(command mode) 2) Visual模式&#xff08;visual mode&#xff09; 2) 输入模式(entry mode) 3) 末行模式(last-line mode) 4) 在/etc/vimrc有给予vim…

JSF 2,PrimeFaces 3,Spring 3和Hibernate 4集成项目

本文展示了如何集成JSF2&#xff0c;PrimeFaces3&#xff0c;Spring3和Hibernate4技术。 它为Java开发人员提供了一个通用的项目模板。 另外&#xff0c;如果Spring不用于业务和数据访问层&#xff0c;则可以提供JSF – PrimeFaces和Hibernate集成项目。 二手技术&#xff1a…