當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
与reCAPTCHA的Spring集成
生活随笔
收集整理的這篇文章主要介紹了
与reCAPTCHA的Spring集成
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
有時我們只需要CAPTCHA ,這是一個可悲的事實。 今天,我們將學(xué)習(xí)如何與reCAPTCHA集成。 因為主題本身并不是特別有趣和高級,所以我們將通過使用Spring Integration處理低級細(xì)節(jié)來過度設(shè)計(?)。 Google決定使用reCAPTCHA的決定取決于兩個因素:(1)這是一種適度良好的CAPTCHA實施方案,具有體面的圖像,并內(nèi)置了對視力障礙者的支持;(2)外包CAPTCHA可使我們在服務(wù)器端保持無狀態(tài)。 更不用說我們在圖書數(shù)字化方面有所幫助。 第二個原因?qū)嶋H上很重要。 通常,您必須在服務(wù)器端生成CAPTCHA,并將預(yù)期結(jié)果存儲在例如用戶會話中。 當(dāng)響應(yīng)返回時,您比較預(yù)期的并輸入了CAPTCHA解決方案。 有時我們不想在服務(wù)器端存儲任何狀態(tài),更不用說實現(xiàn)驗證碼并不是特別有意義的任務(wù)。 因此,擁有現(xiàn)成的和可以接受的東西真是太好了。 完整的源代碼一如既往地可用,我們從一個簡單的Spring MVC Web應(yīng)用程序開始,沒有任何驗證碼。 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'}
); 官方文檔非常簡潔,描述性強,因此我不會深入探討這一細(xì)節(jié)。 當(dāng)您在<form/>包含此小部件時,當(dāng)用戶提交時,您將收到兩個額外的字段: recaptcha_response_field和recaptcha_challenge_field 。 第一個是用戶鍵入的實際文本,第二個是每個請求生成的隱藏令牌。 reCAPTCHA服務(wù)器可能會將它用作會話密鑰,但是我們不在乎,我們要做的就是將此字段進一步傳遞給reCAPTCHA服務(wù)器 。 我將使用HttpClient 4對外部服務(wù)器執(zhí)行HTTP請求,并在Scala中執(zhí)行一些巧妙的模式匹配來解析響應(yīng): 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并不相關(guān)。 但是結(jié)果是! 這樣就可以了,但是顯然不是很壯觀。 您如何用Spring Integration替換低級HttpClient調(diào)用? ReCaptchaVerifier接口(特征)保持不變,因此不必更改客戶端代碼。 但是我們將HttpClientReCaptchaVerifier重構(gòu)為兩個單獨的,較小的,相對高級的抽象類: @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)}}} 請注意,我們不再需要實現(xiàn)ReCaptchaVerifier ,Spring Integration將為我們做到這一點。 我們只需要告訴我們框架應(yīng)該如何使用上面提取的構(gòu)建塊。 我想我還沒有描述Spring Integration是什么以及它是如何工作的。 簡而言之,它是企業(yè)集成模式的非常純凈的實現(xiàn)(有人可能將其稱為ESB)。 消息流是使用XML描述的,可以嵌入到標(biāo)準(zhǔn)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服務(wù)器再返回的消息流。 在必須將ReCaptchaSecured對象轉(zhuǎn)換為HTTP請求并將HTTP響應(yīng)轉(zhuǎn)換為有意義的結(jié)果的方式上,該方法從接口透明返回。 <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,但是整個消息流還是非常簡單的。 首先我們定義網(wǎng)關(guān) ,它是Java接口和Spring Integration消息流之間的橋梁。 ReCaptchaVerifier.validate()的參數(shù)稍后變成一條消息 ,該消息發(fā)送到reCaptchaSecuredForm channel 。 ReCaptchaSecured對象從該通道傳遞到ReCaptchaFormToHttpRequest 轉(zhuǎn)換器 。 轉(zhuǎn)換器的用途是從ReCaptchaSecured對象到Java映射的兩次轉(zhuǎn)換,代表一組鍵值對。 稍后,此映射(通過reCaptchaGoogleServerRequest通道)傳遞到http:outbound-gateway 。 該組件的職責(zé)是將先前創(chuàng)建的地圖轉(zhuǎn)換為HTTP請求并將其發(fā)送到指定的地址。 響應(yīng)返回時,將其發(fā)送到reCaptchaGoogleServerResponse通道。 ReCaptchaServerResponseToResult轉(zhuǎn)換器將采取行動,將HTTP響應(yīng)轉(zhuǎn)換為業(yè)務(wù)結(jié)果(布爾值)。 最終,轉(zhuǎn)換器結(jié)果被路由回網(wǎng)關(guān)。 默認(rèn)情況下,所有操作都是同步發(fā)生的,因此我們?nèi)匀豢梢允褂煤唵蔚腏ava接口進行reCAPTCHA驗證。 信不信由你,這一切正常。 我們不再使用HttpClient (猜測一切都比HttpClient 4 API更好……),而不是一個“巨大”的類,我們有一組較小的,集中的,易于測試的類。 該框架處理接線和底層細(xì)節(jié)。 精彩? 建筑師的夢想還是開發(fā)商的噩夢? 讓我通過引用以上介紹的結(jié)論來總結(jié)我們的努力:在架構(gòu)利益與開發(fā)有效性之間取得平衡 。 Spring Integration能夠從各種異構(gòu)源(如JMS,關(guān)系數(shù)據(jù)庫甚至FTP)接收數(shù)據(jù),以多種方式聚合,拆分,解析和過濾消息,最后使用最奇特的協(xié)議進一步發(fā)送消息。 手工編寫所有代碼是一項非常繁瑣且容易出錯的任務(wù)。 另一方面,有時我們只是不需要所有的幻想,而弄臟我們的手(例如,通過執(zhí)行手動HTTP請求并解析響應(yīng))則更加簡單易懂。 在盲目地將整個體系結(jié)構(gòu)基于非常高級的抽象或基于手工編碼的低級過程之前,請考慮一下后果和平衡。 沒有解決方案可以解決所有問題。 您發(fā)現(xiàn)哪個版本的reCAPTCHA集成更好??? 參考資料: 使用…與reCAPTCHA集成... Java社區(qū)博客上的JCG合作伙伴 Tomasz Nurkiewicz的Spring Integration 。
翻譯自: https://www.javacodegeeks.com/2012/05/spring-integration-with-recaptcha.html
總結(jié)
以上是生活随笔為你收集整理的与reCAPTCHA的Spring集成的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑前黑人被吓到gif(黑人砸电脑)
- 下一篇: 分叉并加入Java 7 – JSR 16