將CAPTCHA添加到您的GWT應用程序

什么是驗證碼?
在一個充滿惡意機器人的世界中,您該怎么做才能保護您寶貴的Web應用程序? 您真正應該做的基本事情之一就是向其中添加CAPTCHA功能。 如果您不熟悉(聽起來有些奇怪),則CAPTCHA是確保用戶實際上是真實人物而不是計算機的簡單方法。 這可以通過挑戰用戶并要求他提供對“問題”的響應來完成。 由于計算機無法解決驗證碼,因此假定輸入正確解決方案的任何用戶都是人。 最常見的方法是要求用戶從出現在屏幕上的變形圖像中鍵入字母或數字。

注冊網站時,您很可能已經看到了一個驗證碼文件。 以下是來自維基百科的CAPTCHA示例。


將SimpleCaptcha添加到您的應用程序
在本教程中,我將CAPTCHA功能集成到Web應用程序中。 我將使用SimpeCaptcha框架 ,該框架用于為Java生成CAPTCHA圖像/答案對。 該站點提供了一個安裝指南 ,但是該指南指的是普通的基于JSP的舊應用程序。 我將向您展示如何將該框架與您喜歡的GWT項目集成。

(我將假設您已經在系統上啟動并運行了GWT ,以及用于Eclipse的Google插件 )

首先,讓我們創建我們的Eclipse項目。 選擇文件 ? Web應用程序項目”,并提供必要的信息,如下圖所示。 該項目的名稱將為“ CaptchaGwtProject”。 確保包括對GWT的支持,但不包括Google App Engine。

在繼續之前,請注意此處。 SimpleCaptcha大量使用AWT類來執行圖像渲染。 但是,您可能知道,App Engine不支持所有JRE類,最具體地說,其中僅包含AWT包中的幾個。 您可以查看AppEngine JRE類白名單以了解更多詳細信息。 因此,不可能將框架合并到將在App Engine上部署的應用程序中,并且僅應將其與在標準JRE上運行的平臺一起使用。

下一步是從SourceForge下載該庫(我使用1.1.1版本 )。 將下載的JAR文件添加到項目的類路徑中。 另外,不要忘記將JAR文件復制到“ CaptchaGwtProject \ war \ WEB-INF \ lib”文件夾,因為嵌入式容器的(Jetty)運行時將需要該文件。 您可以在此處找到該項目的JavaDoc頁面。

設置客戶端
Eclipse將自動創建應用程序的框架,并創建一些示例文件。 找到CaptchaGwtProject類,它是應用程序的入口點。 刪除現有內容,并將其替換為以下內容:

package com.javacodegeeks.captcha.client;import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;public class CaptchaGwtProject implements EntryPoint {private final SignupServiceAsync signupService = GWT.create(SignupService.class);private final Button sendButton = new Button("Sign Up");public void onModuleLoad() {final TextBox usernameField = new TextBox();usernameField.setText("Username here");final TextBox passwordField = new TextBox();passwordField.setText("Password here");final TextBox captchaField = new TextBox();captchaField.setText("CAPTCHA Word here");final Label responseLabel = new Label();        final Image captchaImage = new Image("/SimpleCaptcha.jpg");usernameField.setFocus(true);sendButton.addStyleName("sendButton");RootPanel.get("usernameFieldContainer").add(usernameField);RootPanel.get("passwordFieldContainer").add(passwordField);RootPanel.get("captchaFieldContainer").add(captchaField);RootPanel.get("sendButtonContainer").add(sendButton);RootPanel.get("captchaImageContainer").add(captchaImage);RootPanel.get("responseLabelContainer").add(responseLabel);class MyHandler implements ClickHandler, KeyUpHandler {public void onClick(ClickEvent event) {sendDataToServer();}public void onKeyUp(KeyUpEvent event) {if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {sendDataToServer();}}private void sendDataToServer() {                String username = usernameField.getText();String password = passwordField.getText();String captcha = captchaField.getText();sendButton.setEnabled(false);    signupService.performSignup(username, password, captcha, signupCallback);                }}MyHandler handler = new MyHandler();sendButton.addClickHandler(handler);usernameField.addKeyUpHandler(handler);}private AsyncCallback signupCallback = new AsyncCallback() {        @Overridepublic void onSuccess(Boolean result) {if (result) {Window.alert("CAPTCHA was valid");}else {Window.alert("CAPTCHA was invalid");}            sendButton.setEnabled(true);}        @Overridepublic void onFailure(Throwable caught) {Window.alert("Error occurred while communicating with server");sendButton.setEnabled(true);}        };}

該代碼簡單明了,并且基于自動創建的示例類。 我們為用戶輸入添加了兩個TextBox ,為服務器響應添加了Label 。 我們還添加了一個Image實例,它將作為我們的驗證碼的占位符。 我們將其URL設置為“ /SimpleCaptcha.jpg”,該URL將由框架處理。 最后,使用一個Button來調用對服務器的調用。 AsyncCallback使用布爾值來表示服務器上驗證碼驗證失敗的成功。 請注意,故意遺漏了Web應用程序的某些基本部分(例如用戶輸入驗證),因此我們可以專注于CAPTCHA部分。

接下來,在項目的“ war”文件中找到名為“ CaptchaGwtProject.html”HTML文件。 編輯文件并為我們的GWT對象添加一些容器。 代碼如下:

<!doctype html>
<!-- The DOCTYPE declaration above will set the    -->
<!-- browser's rendering engine into               -->
<!-- "Standards Mode". Replacing this declaration  -->
<!-- with a "Quirks Mode" doctype may lead to some -->
<!-- differences in layout.                        --><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><!--                                                               --><!-- Consider inlining CSS to reduce the number of requested files --><!--                                                               --><link type="text/css" rel="stylesheet" href="CaptchaGwtProject.css"><!--                                           --><!-- Any title is fine                         --><!--                                           --><title>Web Application Starter Project</title><!--                                           --><!-- This script loads your compiled module.   --><!-- If you add any GWT meta tags, they must   --><!-- be added before this line.                --><!--                                           --><script type="text/javascript" language="javascript" src="captchagwtproject/captchagwtproject.nocache.js"></script></head><!--                                           --><!-- The body can have arbitrary html, or      --><!-- you can leave the body empty if you want  --><!-- to create a completely dynamic UI.        --><!--                                           --><body><!-- OPTIONAL: include this if you want history support --><iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe><!-- RECOMMENDED if your web app will not function without JavaScript enabled --><noscript><div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">Your web browser must have JavaScript enabledin order for this application to display correctly.</div></noscript><h1>CAPTCHA Secured Web Application</h1><table align="center"><tr><td colspan="2" style="font-weight:bold;">Please enter your username:</td><td id="usernameFieldContainer"></td></tr><tr><td colspan="2" style="font-weight:bold;">Please enter your password:</td><td id="passwordFieldContainer"></td></tr><tr><td colspan="2" style="font-weight:bold;">Please enter the word:</td><td id="captchaFieldContainer"></td></tr><tr><td id="sendButtonContainer"></td> </tr><tr><td id="captchaImageContainer"></td> </tr><tr><td colspan="2" style="color:red;" id="responseLabelContainer"></td></tr></table></body>
</html>

請注意,對自動生成的文件的唯一更改是在<h1>標記之后。

我們的異步GWT服務將非常簡單,僅執行一項功能。 相應的兩個接口如下所示:

package com.javacodegeeks.captcha.client;import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;@RemoteServiceRelativePath("signup")
public interface SignupService extends RemoteService {boolean performSignup(String username, String password, String userCaptcha);}
package com.javacodegeeks.captcha.client;import com.google.gwt.user.client.rpc.AsyncCallback;public interface SignupServiceAsync {void performSignup(String username, String password, String userCaptcha,AsyncCallback callback);}

(請注意,自動生成的“ greetingService”類已被刪除)

準備服務器端
在服務器端,我們從庫中使用的主要對象是Captcha 。 要檢索驗證碼的值(并將其與用戶輸入進行比較),我們必須獲得對與特定會話關聯的HttpSession對象的引用。 可以通過相應的HttpServletRequest對象檢索HttpSession。 這是標準的Java EE內容。 不要忘記服務器端GWT服務繼承自RemoteServiceServlet ,而RemoteServiceServlet繼承自HttpServletRequest。 可以通過調用getThreadLocalRequest方法獲得基礎請求。 請注意,正如API所提到的,這是本地存儲在線程中的,因此同時調用可以具有不同的請求對象。

服務器端的具體實現如下:

package com.javacodegeeks.captcha.server;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;import nl.captcha.Captcha;import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.javacodegeeks.captcha.client.SignupService;@SuppressWarnings("serial")
public class SignupServiceImpl extends RemoteServiceServlet implements SignupService {public boolean performSignup(String username, String password, String userCaptcha) {HttpServletRequest request = getThreadLocalRequest();HttpSession session = request.getSession();Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);return captcha.isCorrect(userCaptcha);}
}

擴展SimpleCaptcha
最后一步是設置Servlet,該Servlet將生成顯示給用戶的圖像。 通過創建從提供的SimpeCaptchaServlet類繼承的類,可以輕松擴展SimpleCaptcha。 相關代碼如下:

package com.javacodegeeks.captcha.server.servlet;import static nl.captcha.Captcha.NAME;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import nl.captcha.Captcha;
import nl.captcha.backgrounds.GradiatedBackgroundProducer;
import nl.captcha.servlet.CaptchaServletUtil;
import nl.captcha.servlet.SimpleCaptchaServlet;public class ExtendedCaptchaServlet extends SimpleCaptchaServlet {private static final long serialVersionUID = 6560171562324177699L;@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {HttpSession session = req.getSession();Captcha captcha = new Captcha.Builder(_width, _height).addText().addBackground(new GradiatedBackgroundProducer()).gimp().addNoise().addBorder().build();session.setAttribute(NAME, captcha);CaptchaServletUtil.writeImage(resp, captcha.getImage());}}

作為初始化參數傳遞并從父類讀取的“ _width”和“ _height”變量。 要創建一個新的Captcha對象,我們使用Captcha.Builder類(依賴于構建器模式)。 然后,我們將對象傳遞到特定的會話,并將關聯的BufferedImage流傳輸到servlet響應。

請注意,我們的實現每次用戶執行頁面請求時都會生成一個新圖像。 這與在給定會話中使用相同圖像的默認SimpleCaptcha實現不同。

配置Web應用程序
所有組件都通過Web應用程序的“ web.xml”描述符捆綁在一起,在我們的示例中,描述符如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-appPUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd"><web-app><!-- Default page to serve --><welcome-file-list><welcome-file>CaptchaGwtProject.html</welcome-file></welcome-file-list><!-- Servlets --><servlet><servlet-name>signupServlet</servlet-name><servlet-class>com.javacodegeeks.captcha.server.SignupServiceImpl</servlet-class></servlet><servlet-mapping><servlet-name>signupServlet</servlet-name><url-pattern>/captchagwtproject/signup</url-pattern></servlet-mapping><servlet><servlet-name>SimpleCaptcha</servlet-name><servlet-class>com.javacodegeeks.captcha.server.servlet.ExtendedCaptchaServlet</servlet-class><init-param><param-name>width</param-name><param-value>200</param-value></init-param><init-param><param-name>height</param-name><param-value>50</param-value></init-param></servlet><servlet-mapping><servlet-name>SimpleCaptcha</servlet-name><url-pattern>/SimpleCaptcha.jpg</url-pattern></servlet-mapping></web-app>

我們聲明GWT服務(類“ SignupServiceImpl”)和歡迎文件。 這里沒什么特別的。 最后,我們聲明將負責圖像生成并在“'/SimpleCaptcha.jpg”URL下處理請求的servlet(請記住,此請求在GWT入口點中使用)。 我們還提供了servlet的初始化參數(寬度和高度)。

而已! 運行該項目,您應該看到類似以下內容的內容:

每次刷新頁面時,都會創建一個新的CAPTCHA映像。 單擊“注冊”按鈕后,字段內容將發送到服務器,在服務器上用戶提供的CAPTCHA值將根據當前會話中存在的值進行測試。 如果發生故障,我們將看到:


而已。 現在,您的應用程序可以更安全一些。

您可以在此處找到完整的Eclipse項目。

更新:我們的一位讀者詢問是否可以添加“重新加載圖像”功能。 確實有可能,但是從服務器重新獲取圖像時必須小心。 如以下討論所述,瀏覽器將不會重新獲取圖像(因為它具有相同的URL)。 訣竅是添加一個虛擬參數,該參數將在每次刷新時更改。 在這里看看文章:

http://groups.google.gy/group/google-web-toolkit/browse_thread/thread/be9f1da56b5b1c18

事實是,我已經創建了該項目的新版本,可以在此處獲取(按預期用途)。

請享用!

相關文章 :
  • 使用Spring Security保護GWT應用程序
  • GWT 2 Spring 3 JPA 2 Hibernate 3.5教程– Eclipse和Maven 2展示
  • 建立自己的GWT Spring Maven原型
  • GWT EJB3 Maven JBoss 5.1集成教程

翻譯自: https://www.javacodegeeks.com/2010/06/add-captcha-gwt-application.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374596.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374596.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374596.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SQL基礎語句

數據庫面試常見題 一、SQL語言包括數據定義語言、數據操作語言、數據控制語言和事務控制語言1&#xff1a;DDL(Data Definition Language)&#xff0c;是用于描述數據庫中要存儲的現實世界實體的語言。 CREATE TABLE - 創建新表 ALTER TABLE - 變更&#xff08;改變&#xff0…

YYModel Summary

YYModel Effect-> YYModel的作用Provide some data-model method—>提供一些數據模型的方法Convert json to any object, or convert any object to json.->對任何對象轉換成JSON&#xff0c;和對任何JSON轉換為對象Set object properties with a key-value dictionar…

iOS學習——ScrollView圖片輪播和同類控件優先級問題

iOS學習——ScrollView的使用和同類控件優先級問題 1. 布置界面 ScrollView的使用非常簡單&#xff0c;只有三步 1.1 添加一個scrollview 1.2 向scrollview添加內容 1.3 告訴scrollview中內容的實際大小 首先做第一步&#xff0c;布置界面。 拖拽一個scrollview就可以了 就…

Exchanger和無GC的Java

總覽 Exchanger類在線程之間傳遞工作和回收使用的對象方面非常有效。 AFAIK&#xff0c;它也是最少使用的并發類之一。 但是&#xff0c;如果您不需要GC&#xff0c;則使用ArrayBlockingQueue進行日志記錄會更簡單。 交換器類 Exchanger類對于在兩個線程之間來回傳遞數據很有…

構造函數的反射

1 import java.lang.reflect.Constructor;2 3 public class zzbds {4 public static void main(String[] args) {5 6 try{ 7 Class cStudent.class; //獲得無參構造函數8 Constructor constructorc.getConstructor(new Class[]{…

字符串連接“+”int、char、string

String s1 "21" "8" "54";System.out.println(s1);String s2 "21" 8 "54";System.out.println(s2);String s3 "21" 8 "54";System.out.println(s3);21854 21854 21854

使用Spring使用Java發送電子郵件– GMail SMTP服務器示例

對于使用Java發送電子郵件&#xff0c; JavaMail API是標準解決方案。 如官方網頁所述&#xff0c;“ JavaMail API提供了獨立于平臺和協議的框架來構建郵件和消息傳遞應用程序”。 必需的類包含在JavaEE平臺中&#xff0c;但是要在獨立的JavaSE應用程序中使用它&#xff0c;您…

Java字符與數字的計算

先看例子&#xff1a; char ch;int x;int y 7;System.out.print("7的ASCII碼值是&#xff1a;");System.out.println(y);ch 7 2;System.out.print("7 2的char型&#xff1a;");System.out.println(ch);x 7 2;System.out.print("7 2的int型&…

wordcount

源代碼如下 package org.apache.hadoop.examples; import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io…

EJB 3.1全局JNDI訪問

如本系列前面的部分所述&#xff0c;EJB 3.0版規范的主要缺點是缺少可移植的全局JNDI名稱。 這意味著沒有可移植的方式將EJB引用鏈接到應用程序外部的Bean。 EJB v。3.1規范用自己的話填補了這一定義&#xff1a; “一個標準化的全局JNDI名稱空間和一系列相關的名稱空間&#…

Git 分支管理和沖突解決

創建分支 git branch 沒有參數&#xff0c;顯示本地版本庫中所有的本地分支名稱。 當前檢出分支的前面會有星號。 git branch newname 在當前檢出分支上新建分支&#xff0c;名叫newname。 git checkout newname 檢出分支&#xff0c;即切換到名叫newname的分支。 git checkout…

力扣打開轉盤鎖

打開轉盤鎖 評論區大神代碼&#xff1a; public int openLock(String[] deadends, String target) {Set<String> set new HashSet<>(Arrays.asList(deadends));//開始遍歷的字符串是"0000"&#xff0c;相當于根節點String startStr "0000";i…

EJB程序化查找

在上一篇文章中&#xff0c;我們了解了EJB 引用和EJB 注入 。 盡管EJB注入是一種強大的容器工具&#xff0c;可以簡化模塊化應用程序的開發&#xff0c;但有時還是需要執行程序化EJB查找。 讓我們假設&#xff0c;例如&#xff0c;一組不同的EJB實現了由公共業務接口定義的公共…

git克隆/更新/提交代碼步驟及示意圖

1. git clone ssh://flycm.intel.com/scm/at/atSrc 或者git clone ssh://flycm.intel.com/scm/at/atJar 或者git clone ssh://flycm.intel.com/scm/at/atFramework 2. git checkout cpeg/scm/stable 切換分支&#xff0c;然后更新代碼 3. git pull 先把遠程分支上最新的代碼拉到…

C++面試寶典

1.new、delete、malloc、free關系 delete會調用對象的析構函數,和new對應free只會釋放內存&#xff0c;new調用構造函數。malloc與free是C/C語言的標準庫函數&#xff0c;new/delete是C的運算符。它們都可用于申請動態內存和釋放內存。對于非內部數據類型的對象而言&#xff0c…

Google App Engine:在您自己的域中托管應用程序

在Google App Engine中創建新應用程序時&#xff0c;您將獲得一個域名“ yourapp.appspot.com”。 但是&#xff0c;誰會想要以這樣的后綴托管他們的應用程序&#xff08;除非您喜歡它&#xff01;&#xff09;&#xff1f; 為了改善您的應用品牌&#xff0c;最好的辦法是將您的…

從零開始學 iOS 開發的15條建議

事情困難是事實&#xff0c;再困難的事還是要每天努力去做是更大的事實。 因為我是一路自學過來的&#xff0c;并且公認沒什么天賦的前提下&#xff0c;進步得不算太慢&#xff0c;所以有很多打算從零開始的朋友會問我&#xff0c;該怎么學iOS開發。跟粉絲群的朋友交流了一下&a…

垂直居中-父元素高度確定的多行文本(方法二)

除了上一節講到的插入table標簽&#xff0c;可以使父元素高度確定的多行文本垂直居中之外&#xff0c;本節介紹另外一種實現這種效果的方法。但這種方法兼容性比較差&#xff0c;只是提供大家學習參考。 在 chrome、firefox 及 IE8 以上的瀏覽器下可以設置塊級元素的 display 為…

13. 羅馬數字轉整數

羅馬數字轉整數 class Solution {public int romanToInt(String s) {Map<Character,Integer> map new HashMap<Character,Integer>(){{put(I,1);put(V,5);put(X,10);put(L,50);put(C,100);put(D,500);put(M,1000);}};int res 0;for(int i 0;i<s.length();i)…

互聯網金融P2P主業務場景自動化測試

互聯網金融P2P行業&#xff0c;近三年來發展迅速&#xff0c;如火如荼。據不完全統計&#xff0c;全國有3000的企業。“互聯網”企業&#xff0c;幾乎每天都會碰到一些奇奇怪怪的bug&#xff0c;作為在互聯網企業工作的測試人員&#xff0c;風險和壓力都巨大。那么我們如何降低…