Tornado框架完结图形验证码效率,Java实现验证码制作

java web 实现验证码,javaweb实现验证码

验证码的作用:通常的登录或者注册系统时,都会要求用户输入验证码,以此区别用户行为和计算机程序行为,目的是有人防止恶意注册、暴力破解密码等。

实现验证码的思路:用 server 实现随机生成数字和字母组成图片的功能,用
jsp 页面实现显示验证码和用户输入验证码的功能,再用 server
类分别获取图片和用户输入的数据,判断两个数据是否一致。

代码实现

1.编写数字、英文随机生成的 server 类,源码:

  1 package com;
  2 
  3 import java.awt.Color;
  4 import java.awt.Font;
  5 import java.awt.Graphics;
  6 import java.awt.image.BufferedImage;
  7 import java.io.ByteArrayOutputStream;
  8 import java.io.IOException;
  9 import java.io.PrintWriter;
 10 
 11 import javax.imageio.ImageIO;
 12 import javax.servlet.ServletException;
 13 import javax.servlet.ServletOutputStream;
 14 import javax.servlet.http.HttpServlet;
 15 import javax.servlet.http.HttpServletRequest;
 16 import javax.servlet.http.HttpServletResponse;
 17 import javax.servlet.http.HttpSession;
 18 
 19 public class logcheck extends HttpServlet {
 20 
 21     public logcheck() {
 22         super();
 23     }
 24 
 25     
 26     public void destroy() {
 27         super.destroy(); 
 28     }
 29 
 30     public void doGet(HttpServletRequest request, HttpServletResponse response)
 31             throws ServletException, IOException {
 32 
 33         doPost(request, response);
 34     }
 35 
 36 
 37     /*实现的核心代码*/
 38     public void doPost(HttpServletRequest request, HttpServletResponse response)
 39             throws ServletException, IOException {
 40 
 41         response.setContentType("image/jpeg");
 42         HttpSession session=request.getSession();
 43         int width=60;
 44         int height=20;
 45         
 46         //设置浏览器不要缓存此图片
 47         response.setHeader("Pragma", "No-cache");
 48         response.setHeader("Cache-Control", "no-cache");
 49         response.setDateHeader("Expires", 0);
 50         
 51         //创建内存图像并获得图形上下文
 52         BufferedImage image=new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
 53         Graphics g=image.getGraphics();
 54         
 55         /*
 56          * 产生随机验证码
 57          * 定义验证码的字符表
 58          */
 59         String chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 60         char[] rands=new char[4];
 61         for(int i=0;i<4;i++){
 62             int rand=(int) (Math.random() *36);
 63             rands[i]=chars.charAt(rand);
 64         }
 65         
 66         /*
 67          * 产生图像
 68          * 画背景
 69          */
 70         g.setColor(new Color(0xDCDCDC));
 71         g.fillRect(0, 0, width, height);
 72         
 73         /*
 74          * 随机产生120个干扰点
 75          */
 76         
 77         for(int i=0;i<120;i++){
 78             int x=(int)(Math.random()*width);
 79             int y=(int)(Math.random()*height);
 80             int red=(int)(Math.random()*255);
 81             int green=(int)(Math.random()*255);
 82             int blue=(int)(Math.random()*255);
 83             g.setColor(new Color(red,green,blue));
 84             g.drawOval(x, y, 1, 0);
 85         }
 86         g.setColor(Color.BLACK);
 87         g.setFont(new Font(null, Font.ITALIC|Font.BOLD,18));
 88         
 89         //在不同高度输出验证码的不同字符
 90         g.drawString(""+rands[0], 1, 17);
 91         g.drawString(""+rands[1], 16, 15);
 92         g.drawString(""+rands[2], 31, 18);
 93         g.drawString(""+rands[3], 46, 16);
 94         g.dispose();
 95         
 96         //将图像传到客户端
 97         ServletOutputStream sos=response.getOutputStream();
 98         ByteArrayOutputStream baos=new ByteArrayOutputStream();
 99         ImageIO.write(image, "JPEG", baos);
100         byte[] buffer=baos.toByteArray();
101         response.setContentLength(buffer.length);
102         sos.write(buffer);
103         baos.close();
104         sos.close();
105         
106         session.setAttribute("checkcode", new String(rands));
107     }
108 
109     
110     public void init() throws ServletException {
111         // Put your code here
112     }
113 
114 }

 

2.用于显示验证码的页面:

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>index</title>
13     <meta http-equiv="pragma" content="no-cache">
14     <meta http-equiv="cache-control" content="no-cache">
15     <meta http-equiv="expires" content="0">    
16     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17     <meta http-equiv="description" content="This is my page">
18     <!--
19     <link rel="stylesheet" type="text/css" href="styles.css">
20     -->
21   </head>
22   
23   <body>
24   <form action="yanzheng" method="post">
25       <input type="text" name="name" size="5" maxlength="4">
26     <a href="index.jsp"><img border="0" src="logcheck"></a><br><br>
27     &nbsp&nbsp&nbsp&nbsp&nbsp<input type="submit" value="提交">
28   </form>
29   </body>
30 </html>

 

3.用于检验输入的验证码是否正确:

 1 package com;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 
 6 import javax.jms.Session;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 import javax.servlet.http.HttpSession;
12 
13 public class yanzheng extends HttpServlet {
14 
15     public yanzheng() {
16         super();
17     }
18 
19     public void destroy() {
20         super.destroy(); 
21     }
22 
23     public void doGet(HttpServletRequest request, HttpServletResponse response)
24             throws ServletException, IOException {
25 
26         doPost(request, response);
27     }
28     /*核心代码*/
29     public void doPost(HttpServletRequest request, HttpServletResponse response)
30             throws ServletException, IOException {
31 
32         String info=null;
33         /*获取输入的值*/
34         String value1=request.getParameter("name");
35 
36         /*获取图片的值*/
37         HttpSession session=request.getSession();
38         String value2=(String)session.getAttribute("checkcode");
39 
40         /*对比两个值(字母不区分大小写)*/
41         if(value2.equalsIgnoreCase(value1)){
42             info="验证码输入正确";
43         }else{
44             info="验证码输入错误";
45         }
46         System.out.println(info);
47         request.setAttribute("info", info);
48         request.getRequestDispatcher("/login.jsp").forward(request, response);
49     }
50 
51     
52     public void init() throws ServletException {
53         // Put your code here
54     }
55 
56 }

 

4.显示输入结构界面(输入验证码是否正确):

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP 'login.jsp' starting page</title>
13     
14     <meta http-equiv="pragma" content="no-cache">
15     <meta http-equiv="cache-control" content="no-cache">
16     <meta http-equiv="expires" content="0">    
17     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18     <meta http-equiv="description" content="This is my page">
19     <!--
20     <link rel="stylesheet" type="text/css" href="styles.css">
21     -->
22 
23   </head>
24   
25   <body>
26     <%=request.getAttribute("info") %>
27   </body>
28 </html>

5.项目结构、效果截图:

图片 1

图片 2

web 实现验证码,javaweb实现验证码
验证码的作用
:通常的登录或者注册系统时,都会要求用户输入验证码,以此区别用户行为和计算机…

重启服务器,我们再次访问index页面,在用户名密码里输入admin,123如果一切正常,将显示如下页面:

验证码的定义

  • 验证码(captcha):是一种区分用户是人还是计算机的公共全自动程序.
  • 作用:可以防止恶意破解密码,刷票,论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录尝试.
  • 实际上用验证码是现在很多网站通行的方法,我们利用比较简易的方式实现了这个功能.

图片 3

生成图片的实现类

  • ImageServlet类
  1. 定义BufferedImage对象
  2. 获得Graphics对象
  3. 通过Random产生随机验证码信息
  4. 使用Graphics绘制图片
  5. 记录验证码信息到session中
  6. 使用ImageIO输出图片

self.render(‘index.html’)会返回‘index.html’页面

2.1 使用Servlert实现验证码的步骤

验证码包含两部分:

  1. 输入框
  2. 显示验证码的图片
    那么验证码图片是如何获取的?

网页显示验证码

  • <input type="text" id="verifyCode" name="verifyCode" size=6"" />
  • <img alt="验证码" id="safecode" src=<%=request.getContextPath()%>/servlet/ImageServlet">

图片 4

纯代码实现jcaptcha验证码

1、首先创建一个javaWeb工程添加jcaptcha包和它所依赖的包.

commons-collections-3.2.jar
commons-logging-1.2.jar
jcaptcha-1.0-all.jar

2、创建一个jcaptcha单例的Service类,这里是设置验证码样式的关键部分,代码如下:

package cn.v5cn.jcaptchatest.custom;

import java.awt.Font;

import com.octo.captcha.CaptchaFactory;
import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
import com.octo.captcha.component.image.color.RandomRangeColorGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.RandomTextPaster;
import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage;
import com.octo.captcha.component.word.FileDictionary;
import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
import com.octo.captcha.engine.GenericCaptchaEngine;
import com.octo.captcha.image.gimpy.GimpyFactory;
import com.octo.captcha.service.image.ImageCaptchaService;
import com.octo.captcha.service.multitype.GenericManageableCaptchaService;

public class CaptchaServiceSingleton {
    private static ImageCaptchaService service = null;

    public static ImageCaptchaService getService(){
        if(service == null)
            service = generatorCaptchaService();
        return service;
    }
    /**
     * 根据SpringBean的配置文件编写的代码实现
     * */
    public static ImageCaptchaService generatorCaptchaService(){
        //生成随机颜色,参数分别表示RGBA的取值范围
        RandomRangeColorGenerator textColor = new RandomRangeColorGenerator(new int[]{0,255},new int[]{0,180},new int[]{0,210},new int[]{255,255});
        //随机文字多少和颜色,参数1和2表示最少生成多少个文字和最多生成多少个
        RandomTextPaster randomTextPaster = new RandomTextPaster(4, 5, textColor,true);
        //生成背景的大小这里是宽85高40的图片,也可以设置背景颜色和随机背景颜色,这里使用默认的白色
        UniColorBackgroundGenerator colorbgGen = new UniColorBackgroundGenerator(85,40);
        //随机生成的字体大小和字体类型,参数1和2表示最小和最大的字体大小,第三个表示随机的字体
        RandomFontGenerator randomFontGenerator = new RandomFontGenerator(20, 25, new Font[]{new Font("Arial", 0, 10),new Font("Tahoma",0,10)});
        //结合上面的对象构件一个从文本生成图片的对象
        ComposedWordToImage cwti = new ComposedWordToImage(randomFontGenerator,colorbgGen,randomTextPaster);
        //随机文本的字典,这里是使用jcaptcha-1.0-all.jar中的文本字典,字典名称为toddlist.properties
        ComposeDictionaryWordGenerator cdwg = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));

        GimpyFactory gf = new GimpyFactory(cdwg, cwti);

        GenericCaptchaEngine gce = new GenericCaptchaEngine(new CaptchaFactory[]{gf});
        //返回一个Service对象,这里180是验证码存在的时间,单位是秒,200000是最大存储大小
        return new GenericManageableCaptchaService(gce,180,200000,75000);
    }
}

3、创建一个生成验证码的Servlet,代码如下:

package cn.v5cn.jcaptchatest.custom;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class CustomServlet extends HttpServlet {

    private static final long serialVersionUID = 169310818225761427L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        byte[] captChallengeAsJpeg = null;

        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();

        String captchaId = req.getSession().getId();
        BufferedImage challenge = CaptchaServiceSingleton.getService().getImageChallengeForID(captchaId,req.getLocale());

        JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);
        jpegEncoder.encode(challenge);

        captChallengeAsJpeg = jpegOutputStream.toByteArray();

         resp.setHeader("Cache-Control", "no-store");
         resp.setHeader("Pragma", "no-cache");
         resp.setDateHeader("Expires", 0);
         resp.setContentType("image/jpeg");

         ServletOutputStream respOutputStream = resp.getOutputStream();
         respOutputStream.write(captChallengeAsJpeg);
         respOutputStream.flush();
         respOutputStream.close();
    }
}

4、在Web.xml中注册这个Servlet,代码如下:

<servlet>
    <servlet-name>generateValidateCode</servlet-name>
    <servlet-class>cn.v5cn.jcaptchatest.custom.CustomServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>generateValidateCode</servlet-name>
    <url-pattern>/cgvc</url-pattern>
  </servlet-mapping>

5、编写一个使用验证码的页面,代码如下:

<form action="valiServlet" method="post">
    <input type="text" name="customgvc">
    ![](cgvc)
    <input type="submit" value="提交">
</form>

6、编写一个验证Servlet并在web.xml中注册,代码分别如下:

package cn.v5cn.jcaptchatest.custom;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ValidateServlet extends HttpServlet {

    private static final long serialVersionUID = -7173743572400866269L;

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String captchaId = req.getSession().getId();

        String validateCode = req.getParameter("customgvc");

        boolean validateResult = CaptchaServiceSingleton.getService().validateResponseForID(captchaId, validateCode);
        if(validateResult)
            resp.sendRedirect("success.html");
        else
            resp.sendRedirect("fail.html");
    }
}

<servlet>
    <servlet-name>validatServlet</servlet-name>
    <servlet-class>cn.v5cn.jcaptchatest.custom.ValidateServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>validatServlet</servlet-name>
    <url-pattern>/valiServlet</url-pattern>
  </servlet-mapping>

图片 5

2.2 验证码的代码实现

    // /servlet/ImageServlet
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        BufferedImage bi = new BufferedImage(68, 22, BufferedImage.TYPE_INT_RGB);
        Graphics gs = bi.getGraphics();
        Color c = new Color(196, 162, 129);
        gs.setColor(c);
        gs.fillRect(0,0,68,22);

        char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
        Random ran = new Random();
        int len = ch.length,index;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 4; i++) {
            index = ran.nextInt(len);
            gs.setColor(new Color(Test.getCorrectColor(196),Test.getCorrectColor(162),Test.getCorrectColor(129)));
            gs.drawString(ch[index] + "", (15 * i) + 8, 18);
            sb.append(ch[index]);
        }
        request.getSession().setAttribute("piccode", sb.toString());
        ImageIO.write(bi, "JPG", response.getOutputStream());
    }

    //Test.java
    public static int getCorrectColor(int a){
        Random ran = new Random();
        int temp = ran.nextInt(256);
        if (0 <= a - temp && a - temp < 40) {
            temp = a - 40;
        }
        if (a - temp < 0 && temp - a < 40) {
            temp = a + 40;
        }
        return temp;
    }

index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>验证码制作</title>
      <script type="text/javascript">
          function flush_() {
              document.getElementById("captcha").src = "<%=request.getContextPath()%>/servlet/ImageServlet?d="+new Date();
              alert("88");
          }
      </script>
    </head>
    <body>
    验证码: <input type="text" name="captcha" />
    <img alt="captcha" id="captcha" src="<%=request.getContextPath()%>/servlet/ImageServlet" />
    <a href="javascript:
    (function(){document.getElementById('captcha').src='<%=request.getContextPath()%>/servlet/ImageServlet?d='+new Date();})();">看不清楚</a>
    </body>
    </html>
    <%--这里提供了两种js函数定义方法, 其中匿名函数的定义方式与java并不相同.
    这里采用的是(function(a){...})(a)这种格式.前一个()为方法体的定义, 后一个()表示传参并执行.
    匿名函数的缺点在与对一些需要重新解除函数绑定的事件类动作无法解绑?个人理解, 并不懂.
    同时, 在方法体中由于不能使用""进行书写, 则选择使用''代替, 或者使用"字符转义代替.
    在方法体末端的"?d=+"new Date()", 表示通过当前时间来改变网页请求, 从而实现刷新.
    否则浏览器缓存的原因会导致不刷新.
    --%>

什么是验证码?

4.2 Kaptcha的详细配置

<!--kaptcha验证码配置-->
    <servlet>
        <servlet-name>kaptcha</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
        <init-param>
            <description>图片边框, yes or no</description>
            <param-name>kaptcha.border</param-name>
            <param-value>yes</param-value>
        </init-param>
        <init-param>
            <description>边框颜色, white,black,blue...</description>
            <param-name>kaptcha.border.color</param-name>
            <param-value>blue</param-value>
        </init-param>
        <init-param>
            <description>边框厚度,正整数</description>
            <param-name>kaptcha.border.thickness</param-name>
            <param-value>2</param-value>
        </init-param>
<!--        <init-param>
            <description>图片宽度</description>
            <param-name>kaptcha.image.width</param-name>
            <param-value>80</param-value>
        </init-param>
        <init-param>
            <description>图片高度</description>
            <param-name>kaptcha.image.height</param-name>
            <param-value>35</param-value>
        </init-param>-->
<!--       <init-param>
            <description>图片实现类</description>
            <param-name>kaptcha.producer.impl</param-name>
            <param-value>com.google.code.kaptcha.impl.DefaultKaptcha</param-value>
        </init-param>-->
        <init-param>
            <description>文本实现类, 类似文本字符集</description>
            <param-name>kaptcha.textproducer.impl</param-name>
            <param-value>ArithmeticIdentify</param-value>
            <!--<param-value>ChineseTest</param-value>-->
        </init-param>
<!--        <init-param>
            <description>文本集合,验证码值从此集合中获取</description>
            <param-name>kaptcha.textproducer.char.string</param-name>
            <param-value>我们就是这样实现验证码制作然后怎么呢文本类似大小设置长度提交进行尽兴金星影响营养</param-value>
        </init-param>-->
        <init-param>
            <description>设置字体</description>
            <param-name>kaptcha.textproducer.font.names</param-name>
            <param-value>Sim Sun</param-value>
        </init-param>
<!--        <init-param>
            <description>设置字体大小</description>
            <param-name>kaptcha.textproducer.font.size</param-name>
            <param-value>16</param-value>
        </init-param>-->
        <init-param>
            <description>字体颜色</description>
            <param-name>kaptcha.textproducer.font.color</param-name>
            <param-value>blue</param-value>
        </init-param>
        <init-param>
            <description>文字间隔</description>
            <param-name>kaptcha.textproducer.char.space</param-name>
            <param-value>10</param-value>
        </init-param>
<!--        <init-param>
            <description>干扰实现类</description>
            <param-name>kaptcha.noise.impl</param-name>
            <param-value>com.google.code.kaptcha.impl.DefaultNoise</param-value>
        </init-param>-->
        <init-param>
            <description>干扰颜色</description>
            <param-name>kaptcha.noise.color</param-name>
            <param-value>yellow</param-value>
        </init-param>
<!--        <init-param>
            <description>背景实现类</description>
            <param-name>kaptcha.background.impl</param-name>
            <param-value>com.google.code.kaptcha.impl.DefaultBackground</param-value>
        </init-param>-->
        <init-param>
            <description>背景颜色渐变, 开始颜色</description>
            <param-name>kaptcha.background.clear.from</param-name>
            <param-value>green</param-value>
        </init-param>
        <init-param>
            <description>背景颜色渐变, 结束颜色</description>
            <param-name>kaptcha.background.clear.to</param-name>
            <param-value>white</param-value>
        </init-param>
<!--        <init-param>
            <description>文字渲染器</description>
            <param-name>kaptcha.word.impl</param-name>
            <param-value>com.google.code.kaptcha.text.impl.DefaultWordRenderer</param-value>
        </init-param>-->
<!--       <init-param>
            <description>图片样式: FishEyeGimpy鱼眼,WaterRipple水纹,ShadowGimpy阴影,默认水纹</description>
            <param-name>kaptcha.obscurificator.impl</param-name>
            <param-value>com.google.code.kaptcha.impl.ShadowGimpy</param-value>
        </init-param>-->
 <!--       <init-param>
            <description>session中存放验证码的key键</description>
            <param-name>kaptcha.session.key</param-name>
            <param-value>KAPTCHA_SESSION_KEY</param-value>
        </init-param>-->


    </servlet>

    <servlet-mapping>
        <servlet-name>kaptcha</servlet-name>
        <url-pattern>/kaptcha.jpg</url-pattern>
    </servlet-mapping>

那么我们今天需要添加一个图形验证码的功能。首先需要修改前端页面如下:

Java实现验证码制作


图片 6

java.jpg

图片 7

第二章 使用Servlert实现验证码

post请求的url是”/index”,所以我们需要在IndexHandler中再写一个post方法,来处理登录。

第三章 使用Jcaptcha组件实现验证码

图片 8

  • Jcaptcha: 一个用来生成图形验证码的Java开源组件,使用非常简单方便.
    与Spring组合使用,可产生多种形式的验证码.
  • Kaptcha: 一个非常使用的验证码生成工具, 它是可以配置的,
    可以生成各种各样的验证码.

图片 9

第四章 使用Kaptcha组件实现验证码制作

图片 10

第一章 概述

常在网上晃悠的人,对上面这个图片不陌生。特别是在注册、登录、发帖等等时候会频繁出现。那么它有什么作用,它的原理是什么呢?

校验验证码是否正确

  • LoginServlet类
  1. 获取页面验证码
  2. 获取session保存的验证码
  3. 比较验证码
  4. 返回校验结果

使用Servlet实现验证码流程

图片 11


这段是路由规则,r”/index”是规则,支持正则表达式。这条路由代表,url为“/index”的请求指向IndexHandler。那么我们在浏览器中访问127.0.0.1:8080/index的时候,浏览器的请求就会交给IndexHandler来响应。

1.1 验证码概述

  • 为什么要使用验证码
  • 什么是验证码
  • 使用Servlet实现验证码
  • 使用开源组件实现验证码
  • 验证码的发展

图片 12

如图可以发现计算机也可以通过传递URL参数等来执行登录操作

没有验证码带来的问题

  • 对特定用户不断登录破解密码
  • 对某个网站创建账户
  • 对某个网站提交垃圾数据
  • 对某个网站刷票

我们要通过验证码, 由用户肉眼识别其中的验证码信息,
从而区分用户是人还是计算机

图片 13

2.3 验证码的校验

index.jsp

<form action="<%=request.getContextPath()%>/servlet/LoginServlet" method="post">
    验证码: <input type="text" name="captchaNo" />
    <img alt="captcha" id="captcha" src="<%=request.getContextPath()%>/servlet/ImageServlet" />
    <a href="javascript:(function(){document.getElementById('captcha').src='<%=request.getContextPath()%>/servlet/ImageServlet?d='+new%20Date();})();">看不清楚</a>
    <div><input type="submit" value="提交" /></div>
</form>

LoginServlet.java

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String captcha = request.getParameter("captchaNo").toUpperCase();
    System.out.println(captcha);
    System.out.println(request.getSession().getAttribute("piccode"));
    if (request.getSession().getAttribute("piccode").equals(captcha)) response.sendRedirect("/success.jsp");
    else response.sendRedirect("/index.jsp");
    System.out.println("验证完成===========");
}

Test.java

public static int getCorrectColor(int a){
    Random ran = new Random();
    int i = ran.nextInt(41) + (255 - a - 20);
    i = i > 0 ? i : 0;
    i = i > 255 ? 255 : i;
    System.out.print(i+" ");
    return i;
}

在index.html中form表单会向action指向的url发送post请求。

Jcaptcha组件实现验证码实例

项目案例

  • JSP禁用缓存的方式 response.setHeader( “Pragma”, “no-cache” );
    setDateHeader(“Expires”, 0);的用法和什么意思

JSP禁用缓存的方式 使用服务器端控制AJAX页面缓存: response.setHeader( "Pragma", "no-cache" ); response.addHeader( "Cache-Control", "must-revalidate" ); response.addHeader( "Cache-Control", "no-cache" ); response.addHeader( "Cache-Control", "no-store" ); response.setDateHeader("Expires", 0); 单纯的使用 xmlhttp.setRequestHeader("Cache-Control","no-cache")无效。

Cache-Control头域 Cache-Control指定请求和响应遵循的缓存机制。 在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。 请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached. 响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。 各个消息中的指令含义如下: Public指示响应可被任何缓存区缓存。   Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。   no-cache指示请求或响应消息不能缓存   no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。   max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。   min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。   max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

禁用IE缓存 HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。 普通报头中的Cache-Control用于指定缓存指令,缓存指令是单向的(响 应中出现的缓存指令在请求中未必会出现).且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。 请求时的缓存指令包括:no-cache(用于指示请示或响应消息不能缓存)、no-store、max-age、max-stale、min-fresh、only-if-cached; 响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。

例:为了指示IE浏览器(客户端)不要缓存页面,服务器端的jsp程序可以编写如下: response.setHeader(“Cache-Control”, “no-cache”); //response.setHeader(“Pragma”, “no-cache”);作用相当于上行代码,通常两者合用

Expires实体报头域给出响应过期的日期和时间。 为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面, 我们可以使用Expires实体报头域指定页面过期时间。 例:Expires:Thu,15 Sep 2006 16:23:12 GMT HTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。如:为了让浏览器不要缓存页面,也可以利用Expires实体报关域,设置为0,jsp程序如下: response.setDateHeader(“Expires”, “0”);

jcaptcha使用默认样式生成的验证码比较难以识别,所以需要自定义验证码的样式,包括,背景色、背景大小、字体、字体大小、生成的字符数等。相对与kaptcha比较复杂。

首先我们需要在服务器端写一个登录的html文件。

生成图片

  • 生成图片用到的类
  1. BufferedImage图像数据缓冲区
  2. Graphics绘制图片
  3. Color获取颜色
  4. Random生成随机数
  5. ImageIO输出图片

图片 14

4.1 字母数字组合验证码的实现

web.xml

    <!--kaptcha验证码配置-->
    <servlet>
        <servlet-name>kaptcha</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
        <init-param>
            <param-name>kaptcha.border</param-name>
            <param-value>no</param-value>
        </init-param>
        <init-param>
            <param-name>kaptcha.textproducer.font.color</param-name>
            <param-value>black</param-value>
        </init-param>
        <init-param>
            <param-name>kaptcha.textproducer.char.space</param-name>
            <param-value>5</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>kaptcha</servlet-name>
        <url-pattern>/kaptcha.jpg</url-pattern>
    </servlet-mapping>
    <!--
    kaptcha.border:是否显示边框。
    kaptcha.textproducer.font.color:字体颜色
    kaptcha.textproducer.char.space:字符间距
    更多的属性设置可以在com.google.code.kaptcha.Constants类中找到。其中包括:
    kaptcha.border.color:边框颜色
    kaptcha.border.thickness:边框宽度
    kaptcha.textproducer.char.length:产生字符的长度
    kaptcha.textproducer.font.size:产生字符的大小
    kaptcha.image.width:产生图片的宽度
    kaptcha.image.height:产生图片的高度
    -->

index.jsp

    <form action="${pageContext.request.contextPath}/kaptcha" method="post">
        <input type="text" name="kaptchaValidate">
        <img id="vcode"onclick="(function() {document.getElementById('vcode').src
        ='${pageContext.request.contextPath}/kaptcha.jpg?'+new Date();

        })()" title="点击更换" style="vertical-align: middle;" alt="验证图片"
        src="${pageContext.request.contextPath}/kaptcha.jpg" height="35" width="80">
        <input type="submit" value="提交">
    </form>

KaptchaValidateServlet.java

    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        String validate = request.getParameter("kaptchaValidate");
        String validateCode = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);

        if (validate ==null || validateCode == null) response.sendRedirect("/index.jsp");
        else if (!validateCode.equals(validate)) response.sendRedirect("/index.jsp");
        else response.sendRedirect("/success.jsp");
    }

验证码的作用?

一定记得还要添加一条路由

(r”/check_code”, CheckCodeHandler),

图片 15

我们分别介绍一下这段代码中的每个部分。

重启服务器,再次登录页面,那么如果没有错误,点击验证码就可以实现刷新验证码了。

重启服务器,再来访问/index,如果一切正常你会得到如下页面

验证码原理!

首先验证码是一个程序概念,它通过向请求的发起方提出问题,能正确回答的即使人类,反之则为机器。这个程序基于这个样一个重要的假设:提出的问题要容易被人类解答,机器无法解答。在当时的技术条件下,识别扭曲的图形,对于机器来说还是一个很艰难的任务,对于人来说,相对可以接受。所以最开始的验证码是图形验证码,也是比较容易实现的验证码。

到这里我们的图形验证码就实现成功,我们只需要在登录的时候去验证用户输入的验证码和生成图片的code是否一致就判断是否是人工登录。那么业务业务逻辑的设计我们今天不讨论。我们这个验证码还有一个缺点,因为图片加了噪点,扭曲,有时候可能不好辨认,我们需要换一张验证码。我们下面通过一段js来实现点击验证码图片来刷新的功能。代码如下:

方框部分就是验证码,因为我们的图片指向的url是/check_code,但是我们的服务器中还没有,所以获取不到图片,那么我们就需要来写一个返回验证码图片的业务模块。

图片 16

谷歌浏览器按f12打开开发者工具,选中network可以查看浏览器发送的http请求,如下图:

图片 17

我们登录,注册时首先会向服务器发送一个页面请求。服务器在接到这个请求后,随机生成一个字符串,然后将这个字符串画成一张图片,并将这个图片返回给请求用户。用户在收到这个页面之后再次提交请求数据时,需要识别这张图片上的字符,并且填写跟需要提交的数据一并提交给服务器。服务器在收到这些数据后,会首先判断图片上的字符串跟之前生成的字符串是否一致,一致则说明提交合法,反之不合法。

图形验证码的工作流程

业务处理模块,也是我们开发工作的核心。每一个类对应一个业务功能,所有的类必须继承tornado.web.RequestHandler类,这个类是tornado中用来处理请求的类。上面讲到浏览器访问”/index”,这个请求会被路由转发到IndexHandler类。因为是get请求,所以会执行get方法。Self.write(‘hello
world!’),会返回‘hello world!’字符串。所以浏览器也会接收到这个字符串。

增加一个显示验证码的图片标签,一个输入验证码的input标签,重启服务器再次访问

这段代码是服务器部分,写法固定。其中listem函数中的8080代表的是端口,可以修改成任意端口。

验证码处理模块,需要生成一个随机字符串,并且还要返回这个随机字符串生成的图片。Python3中处理图形图形的模块是pillow,2中是PIL。通过这个模块,我们写一个生成随机字符串,和对应图片的函数。因为我们这个里主要是介绍验证码的原理,所以这个函数我们不细讲,验证码处理模块代码如下:

图片 18

为了简单,直接将这个文件命名为index.html放到当前目录。我们需要修改get方法中的代码。

图片 19

图片 20

我们将这段代码运行之后,打开浏览器输入http://127.0.0.1:8080/index,如果一切正常你会得到如下页面。

图片 21

那么我们要返回一个登录的html页面怎么操作呢?

验证码自从2002年提出以来,证明了它的效果后,在互联网上得到了迅速的推广。在发展过程中,出现了图形验证码,语言验证码,邮件验证码,短信验证码等等。但是它们的原理大抵相同。

Self.get_argument(‘user’)可以获取post请求中发过来的数据,参数user对应html中form标签里的元素的name。

重启服务器,再次访问登录页面,如果没有错误会得到如下页面:

可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。

验证码(CAPTCHA)是“Completely Automated Public Turing test to tell
Computers and Humans
Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。

图片 22

图片 23

那么我们今天通过python中的常用的web框架tornado来实现一个图形验证码。通过tornado搭建一个web服务器是非常容易的。下面的代码就是一个通过tornado实现的web服务器。

图片 24

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注