<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 6,comments - 2,trackbacks - 0
    轉自:
    http://my.oschina.net/jawava/blog/8574


    發現這個社區不錯,所以也湊個熱鬧。

    第一篇日志,一定要動手寫才有誠意。

    這兩天要給剛做的外網系統登錄頁面加驗證碼,以前沒做過。上網搜了一下,資料很多。
    驗證碼校驗稱作captcha:
    Completely Automated Public Test to tell Computers and Humans Apart
    專業點兒的翻譯是:全自動區分計算機和人類的圖靈測試。
    CAPTCHA的目的很明確,就是區分計算機和人類的一種程序算法,
    這種程序必須能生成并評價人類能很容易通過但計算機卻通不過的測試。

    網上能查到不少實現方案,簡單的寫個jsp就行了,技術含量不高。搜了一圈后,
    感覺還是用個正規點兒比較合適,然后就鎖定了JCaptcha,到其官方網站上看了看:
    http://jcaptcha.octo.com/confluence/display/general/Home

    JCaptcha提供了
    Provide robust and reliable CAPTCHA implementation framework for JAVA
    Provide accessible CAPTCHA implementations
    Provide multi-type challenge (text, sound, image)

    它用上百個類來實現了如此簡單的功能,這是為什么呢?官方給的解釋是
    1、學術界能不斷的發明(或發現)一些人類容易處理而機器不能很好處理的問題。
    JCaptcha高屋建瓴的給出了一種通用的定義和表達這種問題并用于識別的方案。
    也就是識別方案的可擴展性。
    2、實現了若干引擎和組件,通過配置這些引擎和組件,可以方便的修改自己程序
    captcha構件的算法。這樣,在抵御惡意訪問時,可以不用改變代碼,靈活快速的
    改變captcha策略,從而更好的保護系統。

    個人覺的說的挺好,第一點對于我們來說倒是次要的,主要第二點比較有意義。
    然后就試了試。下面是具體需要做的工作:

    一,從官網上下個jcaptcha-1.0-all.jar,加入到項目中,
    官方的2.0還沒有正式版,所以先用1.0吧。

    二,官網上介紹了幾種和項目結合的具體方案,最簡單的方式很快走通,圖片很難看,
    而且不具有可配置性,肯定不行。所以選擇通過spring來整合的方式,
    spring是整合和配置的平臺,把jcaptcha的服務和引擎還有組件配置成spring的bean。
    示例如下:
    <?xml version="1.0" encoding="gb2312"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
            "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans  default-autowire="byName">

        <bean id="captchaServlet" class="com.jawava.XXXX.XXX.TopImageCaptchaServlet" />

    <bean id="captchaService" class="com.octo.captcha.service.multitype.GenericManageableCaptchaService">
    <description>驗證碼服務</description>
    <constructor-arg index="0"><ref bean="imageEngine"/></constructor-arg>
    <constructor-arg index="1"><value>300</value></constructor-arg><!--超時時間 秒-->
    <constructor-arg index="2"><value>20000</value></constructor-arg><!--最大并發數-->
    <constructor-arg index="3"><value>20000</value></constructor-arg>& lt;!--第四個參數官網示例上沒有給出,會報錯,后來看了API才知道少了個參數-->
    </bean>

    <bean id="imageEngine" class="com.octo.captcha.engine.GenericCaptchaEngine">
    <description>圖片引擎</description>
    <constructor-arg index="0">
    <list>
    <ref bean="CaptchaFactory"/>
    </list>
    </constructor-arg>
    </bean>

    <bean id="CaptchaFactory" class="com.octo.captcha.image.gimpy.GimpyFactory" >
    <description>驗證碼工廠</description>
    <constructor-arg><ref bean="wordgen"/></constructor-arg>
    <constructor-arg><ref bean="wordtoimage"/></constructor-arg>
    </bean>

    <bean id="wordgen" class= "com.octo.captcha.component.word.wordgenerator.RandomWordGenerator" >
    <description>文字產生器,提供了好幾種實現,經過比較選用了這種</description>
    <constructor-arg index="0"><value>0123456789</value></constructor-arg>
    </bean>

    <bean id="wordtoimage" class="com.octo.captcha.component.image.wordtoimage.ComposedWordToImage" >
    <description>圖片生成器</description>
    <constructor-arg index="0"><ref bean="fontGenRandom"/></constructor-arg>
    <constructor-arg index="1"><ref bean="backGenUni"/></constructor-arg>
    <constructor-arg index="2"><ref bean="simpleWhitePaster"/></constructor-arg>
    </bean>

    <bean id="fontGenRandom" class="com.octo.captcha.component.image.fontgenerator.RandomFontGenerator" >
    <description>文字轉換圖片</description>
    <constructor-arg index="0"><value>20</value></constructor-arg><!--字體最小尺寸-->
    <constructor-arg index="1"><value>20</value></constructor-arg><!--字體最大尺寸-->
    </bean> 

    <bean id="backGenUni" class="com.octo.captcha.component.image.backgroundgenerator.GradientBackgroundGenerator" >
    <constructor-arg index="0"><value>62</value></constructor-arg><!--背景圖片寬度-->
    <constructor-arg index="1"><value>22</value></constructor-arg><!--背景圖片高度-->
    <constructor-arg type="java.awt.Color" index="2">
    <ref bean="colorGrey"/>
    </constructor-arg> 
    <constructor-arg type="java.awt.Color" index="3">
    <ref bean="colorGreen"/>
    </constructor-arg>

    </bean>

    <bean id="simpleWhitePaster" class="com.octo.captcha.component.image.textpaster.SimpleTextPaster" >
    <constructor-arg type="java.lang.Integer" index="0">
    <value>4</value><!--字符最少個數-->
    </constructor-arg>
    <constructor-arg type="java.lang.Integer" index="1">
    <value>4</value><!--字符最多個數-->
    </constructor-arg>
    <constructor-arg type="java.awt.Color" index="2">
    <ref bean="colorFont"/>
    </constructor-arg>
    </bean>

    <bean id="colorGrey" class="java.awt.Color" >
    <constructor-arg index="0"><value>200</value></constructor-arg>
    <constructor-arg index="1"><value>255</value></constructor-arg>
    <constructor-arg index="2"><value>200</value></constructor-arg>
    </bean>
    <bean id="colorGreen" class="java.awt.Color" >
    <constructor-arg index="0"><value>110</value></constructor-arg>
    <constructor-arg index="1"><value>120</value></constructor-arg>
    <constructor-arg index="2"><value>200</value></constructor-arg>
    </bean>
    <bean id="colorFont" class="java.awt.Color" >
    <constructor-arg index="0"><value>60</value></constructor-arg>
    <constructor-arg index="1"><value>60</value></constructor-arg>
    <constructor-arg index="2"><value>60</value></constructor-arg>
    </bean>
    </beans>



    這里面具體用哪個component,需要看ApI,我把包里提供的現成的組件基本上試了大半,
    最后選擇了如上的配置,選擇的標準一是美觀,二是識別率。識別率太低了,用戶體驗會下降。

    三、配置好后,JCaptcha這邊的工作就完成了。下面就是和項目的結合。
    1、首先專門寫個CaptcahServlet用來獲取驗證碼,由于要在servlet里注入spring的bean,
    所以用了代理的方式。代理類網上有,都是固定寫法,這里就不貼了。
    CaptcahServlet主要部分如下:
    @Override
    public void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
    throws ServletException, IOException, RuntimeException {

    byte[] captchaChallengeAsJpeg = null;
    //輸出jpg的字節流
    ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
    try {
    // get the session id that will identify the generated captcha.
    //the same id must be used to validate the response, the session id is a good candidate!
    String captchaId = httpServletRequest.getSession().getId();
    // call the ImageCaptchaService getChallenge method
    BufferedImage challenge =
    (BufferedImage) captchaService.getChallengeForID(captchaId,
                httpServletRequest.getLocale());

    // a jpeg encoder
        JPEGImageEncoder jpegEncoder =
                JPEGCodec.createJPEGEncoder(jpegOutputStream);
        jpegEncoder.encode(challenge);

    } catch (IllegalArgumentException e) {
        httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    } catch (CaptchaServiceException e) {
        httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }

    captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

    // flush it in the response
    httpServletResponse.setHeader("Cache-Control", "no-store");
    httpServletResponse.setHeader("Pragma", "no-cache");
    httpServletResponse.setDateHeader("Expires", 0);
    httpServletResponse.setContentType("image/jpeg");
    ServletOutputStream responseOutputStream =
            httpServletResponse.getOutputStream();
    responseOutputStream.write(captchaChallengeAsJpeg);
    responseOutputStream.flush();
    responseOutputStream.close();
        }



    然后在web.xml配置:

    <servlet>
    <servlet-name>CaptchaProxy</servlet-name>
    <servlet-class>com.jawava.XXXXX.XXX.TopHttpServletProxy</servlet-class>
    <init-param>
    <param-name>targetServlet</param-name>
    <param-value>captchaServlet</param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
    <servlet-name>CaptchaProxy</servlet-name>
    <url-pattern>/topJcaptcha</url-pattern>
    </servlet-mapping>



    2、目前項目的登錄頁面是jsp,結合很方便,在原有頁面上加上
    <img src="/topJcaptcha" /> <input type="text" name="jcaptcha" value="" />
    那個img就是校驗碼。
    需要的話,再加上個換圖片的功能,很簡單。

    3、驗證環節。我是在原來的驗證用戶密碼的邏輯前,加上了驗證碼的校驗邏輯。
    很簡單的幾句話,代碼如下:

    Boolean isResponseCorrect =Boolean.FALSE;
            //需要sessionId 來驗證校驗碼
            String sessionId = request.getSession().getId();
    //首先校驗驗證碼
            try {
                isResponseCorrect = captchaService.validateResponseForID(sessionId,
                 captcha_input);
                if(!isResponseCorrect) {
                 throw new RuntimeException("輸入的驗證碼有誤,請重新輸入");
                }
            } catch (CaptchaServiceException e) {
                 //should not happen, may be thrown if the id is not valid
             throw new RuntimeException("校驗驗證碼時出現不明錯誤",e);
            }



    四、如此就可以測試了。通過反復調整參數,達到了比較美觀的效果,但是文字始終
    不在圖片的正中,而是靠上,甚至都把文字掩蓋了一半。翻看了半天API,也看不出
    個端倪。只好去翻源代碼了。問題出在
    com.octo.captcha.component.image.textpaster.SimpleTextPaster這個類,它把文字
    圖片往背景圖片放時,把文字的位置放在了背景圖片一半的高度上,這就是問題所在。
    修改代碼重新打了個jar包。替換一下,重啟后一切ok。
    posted on 2012-10-18 10:16 achan2bj 閱讀(1308) 評論(2)  編輯  收藏 所屬分類: j2ee

    FeedBack:
    # re: 運用Jcaptcha做驗證碼總結
    2016-02-19 04:36 | hz
    謝謝,最后一句解救人啊。  回復  更多評論
      
    # re: 運用Jcaptcha做驗證碼總結
    2016-02-19 09:35 | achan2bj
    @hz
    是指修改com.octo.captcha.component.image.textpaster.SimpleTextPaster這個類后,重新打包替換嗎?  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 一道本不卡免费视频| 亚洲熟妇AV一区二区三区浪潮| 污视频网站在线免费看| 国产大片线上免费看| 亚洲砖码砖专无区2023 | 亚洲人妖女同在线播放| 3344永久在线观看视频免费首页| 亚洲小视频在线观看| 精品福利一区二区三区免费视频| 亚洲日韩乱码久久久久久| 国产一卡2卡3卡4卡2021免费观看| 亚洲国产美女福利直播秀一区二区 | 三年在线观看免费观看完整版中文| 亚洲区小说区图片区| 中文字幕在线视频免费观看 | 一二三四免费观看在线电影| ww亚洲ww在线观看国产| 野花高清在线电影观看免费视频| 亚洲一区二区无码偷拍| 免费观看四虎精品国产永久| 又黄又大的激情视频在线观看免费视频社区在线 | 亚洲日韩一区精品射精| 波多野结衣一区二区免费视频| 人禽伦免费交视频播放| 亚洲精品国产成人99久久| 国产在线a免费观看| 无套内射无矿码免费看黄| 亚洲成A∨人片在线观看不卡 | 无码专区AAAAAA免费视频| 精品亚洲成A人无码成A在线观看| 国产精品久免费的黄网站| 久青草视频在线观看免费| 亚洲国产成人精品电影| 亚洲国产精品自在拍在线播放| 免费日本一区二区| 亚洲精品无码中文久久字幕| 国产国拍精品亚洲AV片| **一级毛片免费完整视| 免费无码一区二区| 亚洲国产亚洲综合在线尤物| 啊v在线免费观看|