• Java生成中文验证码


     

    1980,为了使每一个汉字有一个全国统一的编码,我国制定了”中华人民共和国国家标准信息交换汉字编码”,标准代号为GB2312-80,这种编码又称为国标码,国标码字符集中共收录了一级汉字3755,二级汉字3008,图形符号682,3项字符总计7445.

    国标GB2312-80中规定,所有的国标汉字及符号分配在一个94,94列的方阵中,方阵的每一个行称为一个”区”,编号为01-94,每一个列称为一个”位”,编号为01-94,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的4个阿拉伯数字就是他们的”区位码”,区位码的前两位是它的区号,后两位是它的位号,用区位码就可以唯一的确定一个汉字或符号,反之,任何一个汉字或符号也都对应一个唯一的区位码.

    所有的汉字和符号所在的区 分为以下4个组.

    1). 01-15,图形符号,其中01-09区分标准符号区,10-15区为自定义符号区

    2). 16-55一级常用汉字区,包括3755个一统汉字.40个区中的汉字是按汉语拼音排序的.同音字按笔划顺序排序.其中55区的90-94位未定义汉字

    3). 56-87二级汉字区,包括3008个二级汉字,按部首排序

    4). 89-94,自定义汉字区

    其中,10-15区的自定义符号区和第88-94区的自定义符号区可由用户自定义,国标码中未定义的符号和汉字.

    与汉字的区位码类似的还有汉字机内码,它是在汉字区位码的区码和位码上分别加上A0H(这里的H表示前两位数字为16进制数)而得到的,使用机内码表示的一个汉字占用2个字节,分别称为高位字节和低位字节.这两位字节的机内码按一下规则表示:

    高位字节=区码+20H+80H(或区码+A0H),

    低位字节=位码+20H+80H(或位码+A0H),

    例如,汉字”啊”的区位码为1601,区码和位码分别用16进制表示即为1001H.它的机内码的高位字节为B0H,低位字节为A1H.机内码就是B0A1H.

     

    实例截图

    前端代码

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>中文验证码</title>
        <link href="css2/css.css" rel="stylesheet" type="text/css" />
        <style type="text/css">
            table {
                width:560px;
                border-collapse:collapse; /* 合并单元格之间的边 */
                border:1px solid #0099aa;
                font:normal 12px/1.5em "宋体", Verdana,Lucida, Arial, Helvetica, sans-serif;
            } /* 定义表格的整体宽度以及边框样式,并且定义表格内所有文字的样式 */
        
        </style>
        <script type="text/javascript">
            function changeCode(){
                document.getElementById("imgcode").src="checkCode?nocache="+new Date().getTime();
            }
        </script>
      </head>
      
      <body onload="checkCode">
            <form  id="regist" method="post" >    
            <table align="center" border="1" bordercolor="#0099aa">
                
                <tr>
                    <td align="right" width="130px">用户名:</td>
                    <td >
                        <input type="text" name="name" id="name" />
                        <font color="red">* 用户名由字母数字和下划线组成</font>
                    </td>
                </tr>
    
                <tr>
                    <td align="right">验证码:</td>
                    <td >
                        <img title="看不清,点击更换验证码" style="cursor:pointer" id="imgcode" alt="" src="checkCode" onclick="changeCode()" >
                    </td>
                </tr>
                <tr>
                    <td align="right">输入验证码:</td>
                    <td><input type="text" name="code" id="code" /></td>
                </tr>
                <tr>
                    <td></td>
                    <td>
                        <input type="submit" value="注 册"/>&nbsp;&nbsp;
                        <input type="reset" value="重 置" />
                    </td>
                    
                </tr>
            </table>
        </form>
      </body>
    </html>

    xml中配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <servlet>
        <servlet-name>ChineseCheckCode</servlet-name>
        <servlet-class>com.webapp.service.ChineseCheckCode</servlet-class>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>ChineseCheckCode</servlet-name>
        <url-pattern>/checkCode</url-pattern>
      </servlet-mapping>
      
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>

    服务端生成文字验证码,需要使用 response.setContentType("image/jpeg");指定生成的响应是图片

     

    package com.webapp.service;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.geom.AffineTransform;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     *
     *  ChineseCheckCode.java    
     *
     *  @version : 1.1
     *  
     *  @author  : 苏若年    <a href="mailto:DennisIT@163.com">发送邮件</a>
     *    
     *  @since     : 1.0        创建时间:    2013-2-13        下午06:45:59
     *     
     *  TODO     :    class ChineseCheckCode.java is used for ...
     *
     */
    public class ChineseCheckCode extends HttpServlet {
    
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            //禁止缓存
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "No-cache");
            response.setDateHeader("Expires", 0);
            // 指定生成的响应是图片
            response.setContentType("image/jpeg");
            
              int width = 155;      //指定验证码的宽度
            int height = 45;      //指定验证码的高度
            BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
            Graphics graphics = image.getGraphics();      //获取Graphics类的对象
            Random random = new Random();          //实例化一个Random对象
            Font mFont = new Font("宋体", Font.ITALIC, 26);   //通过Font构造字体
            graphics.setColor(getRandomColor(200, 250)); //设置颜色
            graphics.fillRect(0, 0, width, height);         
            graphics.setFont(mFont);    //设置字体
            graphics.setColor(getRandomColor(180, 200)); //设置文字的颜色
            
            String chckcode = "";
            String ctmp = "";
            for(int i=0; i<4; i++){
                String[] rBase = { "0", "1", "2", "3", "4", "5", "6", "7", "8",
                        "9", "a", "b", "c", "d", "e", "f" };
                //生成第一位的区码
                int rand1 = random.nextInt(3)+11;    //生成11到14之间的随机数
                String strR1 = rBase[rand1];
                //生成第二位的区码
                int rand2 ;
                if(rand1 == 13){
                    rand2 = random.nextInt(7);        //生成0-7之间的随机数
                }else{
                    rand2 = random.nextInt(16);        //生成0-16之间的随机数
                }
                String strR2 = rBase[rand2];
                
                //生成第一位的位码
                int rand3 = random.nextInt(15)+1;    //生成1到16之间的随即数
                String strR3 = rBase[rand3];
                //生成第二位的位吗
                int rand4;
                if(rand3==10){
                    rand4 = random.nextInt(15)+1;    //生成1到16之间的随机数
                }else if(rand3==15){
                    rand4 = random.nextInt(15);        //生成0到15之间的随机数
                }else{
                    rand4 = random.nextInt(16);        //生成0到16之间的随机数
                }
                String strR4 = rBase[rand4];
                
                //将生成的机内码转换为汉字
                byte[] bytes = new byte[2];
                //将生成的区码保存到字节数组的第一个元素中
                String strR12 = strR1 + strR2;
                int tempLow = Integer.parseInt(strR12, 16);
                bytes[0] = (byte) tempLow;
                
                String strR34 = strR3 + strR4;
                int tempHigh = Integer.parseInt(strR34, 16);
                bytes[1] = (byte) tempHigh;
                
                ctmp = new String(bytes);            //根据字节数组生成汉字
                chckcode = chckcode + ctmp;
                Color color = new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110));
                graphics.setColor(color); 
                
                 /** **随机缩放文字并将文字旋转指定角度* */
                Graphics2D graphics2d = (Graphics2D) graphics;
                //实例化AffineTransform类的对象
                AffineTransform trans = new AffineTransform();
                //进行旋转
                trans.rotate(random.nextInt(25) * 3.14 / 180, 26 * i + 8, 7);
                
                // 缩放文字
                float scaleSize = random.nextFloat() +0.7f;
                if (scaleSize > 1f) scaleSize = 1f;
                trans.scale(scaleSize, scaleSize);   //进行缩放
                graphics2d.setTransform(trans);
                graphics.drawString(ctmp, width/6 * i+30, height/3+5);
            }
            //将生成的验证码保存到Session中
            HttpSession session = request.getSession(true); 
               session.setAttribute("chckcode", chckcode);
               graphics.dispose();
               ImageIO.write(image, "JPEG", response.getOutputStream());
        }
    
    
        /**
         * 生成随即颜色
         * @param fc
         * @param bc
         * @return
         */
        public Color getRandomColor(int fc, int bc){
            Random random = new Random();
            Color randomColor = null;
            if(fc>255) fc=255;
            if(bc>255) bc=255;
            //设置个0-255之间的随机颜色值
            int r=fc+random.nextInt(bc-fc);
            int g=fc+random.nextInt(bc-fc);
            int b=fc+random.nextInt(bc-fc);
            randomColor = new Color(r,g,b);
            return randomColor;//返回具有指定红色、绿色和蓝色值的不透明的 sRGB 颜色
        }
    }

     

    转载请注明出处:[http://www.cnblogs.com/dennisit/archive/2013/02/16/2913263.html]

    在线交谈

  • 相关阅读:
    httpclient + TestNG 接口自动测试 第二章
    httpclient + TestNG 接口自动测试 第一章
    Kafka-manager启动命令
    多台服务器搭建Spark集群
    Scala学习 -- 基础语法
    Spark学习 -- RDD
    Spark 学习
    Angular constructor和OnInit的区别和适用场景
    TypeScript基础学习 —— 变量声明
    TypeScript基础学习 —— 基础类型
  • 原文地址:https://www.cnblogs.com/dennisit/p/2913263.html
Copyright © 2020-2023  润新知