轻松学会网页中验证码的生成(JAVA)
    Wednesday, March 15, 2017
    1:14 PM
    验证码生成的基本流程
    1.验证码的生成,我们能够看到是用Graphics对象画出来的。对象我们必须要获得Graphics对象
    1-1,Graphics对象的获取,要通过BufferedImage获得
    [html] view plain copy
    print?

    1. <span style=”font-size:18px;”>int width=100;//确定框框的大小
    1. int height=40;
    1. BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    1. Graphics g=bfi.getGraphics();//获得Graphics对象就可以画图

    1-2,一般的验证码背景框都是白色的
    [html] view plain copy
    print?

    1. <span style=”font-size:18px;”> //1,设置背景(白框框)
    2. g.setColor(Color.WHITE);//白色的画笔
    3. g.fillRect(0, 0, width, height);//画矩形矩形框框

    1-3,保存数据(后台验证使用)和设置字体样式(美观)
    [html] view plain copy
    print?

    1. String str=””;//保存数据
    2. Random rom=new Random();
    3. //设置字体的大写与粗
    4. g.setFont(new Font(“a”, Font.BOLD,20));
      1. 1-4.生成具体的数值,以及随机生成的颜色

    [html] view plain copy
    print?

    1. for(int i=0;i<4;i++){
    1. int num=rom.nextInt(10);//生成的随机数
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawString(“”+num, 20*i, 20+rom.nextInt(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下
    1. //PS:位置需要明确些,
    1. }
      1. 1-5.一般的数字容易被其他软件直接识别出来,为了防黑。稍微加一点干扰线

    [html] view plain copy
    print?

    1. //画出一些干扰线
    1. for (int i = 0; i < 10; i++) {
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是随机,x,y的值不要超过矩形框框
    1. }
      1-6.销毁Graphics对象和存储图片

    [html] view plain copy
    print?

    1. <span style=”white-space:pre”> g.dispose();//销毁对象
    1. ImageIO.write(bfi, “JPEG”, res.getOutputStream());//图片用字节流 直接得到 PS::: res是Servlet里面的。

    这样验证码就生成了,那我们如何导入到前台去呢
    2,具体实现
    前台代码呈现():
    [html] view plain copy
    print?

    1. 用户登录
    1. 用户名:<input type=”text” name=”nametext”/>
    1. 密 码:<input type=”text” name=”psd”/>
    1. 请输入验证码:<input type=”text”/>
    1. <img <span style=”color:#ff0000;”>src=”/IMG/immg” id=”aid”/><a href=”javascript:flush()” >看不清

    1. src的地址来源就是从后台发过来的。路径是很有意思的。
      2-1 步骤
      项目里面 myeclipse —> src —>new Servlet 出现如下:

    Source folder:  IMG/src  Package:  cn.hncu.comservlet  [3 Enclosing type:  private  Na me:  Modifiers:  Superclass:  I nte rfaces:  i mgdemol  @ pu blic C) default  abstract final  static  javax.servlet.http.HttpServlet  B rcMsem  B rcMsem  Browse  protected  B rcMsem  Add.„  Remove  Template to use: I] Default template for Servlet  Which method stubs would you like to create?  C] I nherited abstract methods doGetO  C] Constructors from su perclass C] doPostO  init() and destroyO  C] d 0 Delete()  C] getServletI nfoO
    点击——》next 出现如下页面:
    Servlet/JSP Class Name:  Servlet/JSP Name:  Servlet/JSP Mapping URL:  File Path of web.xml:  Display Name:  Descri ption:  cn.hncu.com.setvlet.imgdemol  i mg demo  'servlet/imgdemcl  /lMG/WebRootN.'EB4NF  B rowsem
    这个配置会自动到项目里面的web-INF文件夹里面web.xml。这个框框里面的值就是前台 src里面写的需要访问的路径,——> 点击完成就行了。
    自动了。生成如下界面:
    1  2  3  4  5  6  7  8  9  ackage cn.hncu.com.servlet;  import javax. serv1et.http.HttpServ1et;  public class aaaa extends HttpServ1et {
    在这里就可写之前的代码。但是需要注意,我们必须通过覆盖这个方法才能有效:
    [html] view plain copy
    print?

    1. protected void service(HttpServletRequest req, HttpServletResponse resp)//自动生成 输入 <span style=”font-family: Arial, Helvetica, sans-serif;”>service 补全,自动生成
    1. throws ServletException, IOException {
    1. // TODO Auto-generated method stub
    1. super.service(req, resp);
    1. }
      具体的代码如下:

    [html] view plain copy
    print?

    1. package cn.hncu.com.servlet;
    1. import java.awt.Color;
    1. import java.awt.Font;
    1. import java.awt.Graphics;
    1. import java.awt.image.BufferedImage;
    1. import java.io.FileOutputStream;
    1. import java.io.IOException;
    1. import java.util.Random;
    1. import javax.imageio.ImageIO;
    1. import javax.servlet.ServletException;
    1. import javax.servlet.ServletRequest;
    1. import javax.servlet.ServletResponse;
    1. import javax.servlet.http.HttpServlet;
    1. import javax.servlet.http.HttpServletRequest;
    1. import javax.servlet.http.HttpServletResponse;
    1. public class Imgdemo extends HttpServlet {
    1. Override
    1. public void service(ServletRequest req, ServletResponse res)
    1. throws ServletException, IOException {
    1. int width=100;//确定框框的大小
    1. int height=40;
    1. BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    1. Graphics g=bfi.getGraphics();//获得Graphics对象就可以画图
    1. //1,设置背景(白框框)
    1. g.setColor(Color.WHITE);//白色的画笔
    1. g.fillRect(0, 0, width, height);//画矩形矩形框框
    1. //2,具体生成随机数
    1. String str=””;//保存数据
    1. Random rom=new Random();
    1. //设置字体的大写与粗
    1. g.setFont(new Font(“a”, Font.BOLD,20));
    1. //画出具体的图片
    1. for(int i=0;i<4;i++){
    1. int num=rom.nextInt(10);//生成的随机数
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawString(“”+num, 20*i, 20+rom.nextInt(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下
    1. //PS:位置需要明确些,
    1. }
    1. //画出一些干扰线
    1. for (int i = 0; i < 10; i++) {
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是随机,x,y的值不要超过矩形框框
    1. }
    1. g.dispose();
    1. ImageIO.write(bfi, “JPEG”, res.getOutputStream());//图片用字节流 直接得到
    1. }
    1. }<span style=”font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);”>

    前台代码:
    [html] view plain copy
    print?

    1. <%@ page language=”java” import=”java.util.“ pageEncoding=”UTF-8”%*>
    1. <%
    1. String path = request.getContextPath();
    1. String basePath = request.getScheme()+”://“+request.getServerName()+”:”+request.getServerPort()+path+”/“;
    1. %>
    1. **

    1. <base href=”<%=basePath%>”>
    1. My JSP ‘img.jsp’ starting page
    1. <meta http-equiv=”pragma” content=”no-cache”>
    1. <meta http-equiv=”cache-control” content=”no-cache”>
    1. <meta http-equiv=”expires” content=”0”>
    1. <meta http-equiv=”keywords” content=”keyword1,keyword2,keyword3”>
    1. <meta http-equiv=”description” content=”This is my page”>
    1. <!—
    1. —>
    1. <script type=”text/javascript”>
    1. function flush(){
    1. var text=document.getElementById(“aid”);
    1. var date =new Date();
    1. var tt=date.getTime();
    1. text.src=”/IMG/immg?”+tt;
    1. }
    1. 用户登录
    1. 用户名:<input type=”text” name=”nametext”/>
    1. 密 码:<input type=”text” name=”psd”/>
    1. 请输入验证码:<input type=”text”/>
    1. <img src=”/IMG/immg” id=”aid”/><a href=”javascript:flush()” >看不清

    1. 对于前台代码需要解释一下:

    当我们的的验证码传过来看不清的时候需要刷新,而浏览器有自动记忆的功能,当没有新的参数传进来的时候,浏览器是不会刷新的,所以我们需要手动的去写一个js控制参数传,我们知道,只有时间是不会变化的,所有我们采用时间来作为参数传递。
    PS:自己坑了一段时间的问题:验证码的路径问题。前端的“/”表示 tomcat目录,在项目内部,如web.xml中“/”表示该项目下。也就是说,他们两个的目录差了一层。
    最后附上自己在测试的时候的代码以及修改数字形状的问题,如改成2D的效果更不错。都有很明显的记录。
    [html] view plain copy
    print?

    1. package cn.hncu.com;
    1. import java.awt.Color;
    1. import java.awt.Font;
    1. import java.awt.Graphics;
    1. import java.awt.Graphics2D;
    1. import java.awt.geom.AffineTransform;
    1. import java.awt.image.BufferedImage;
    1. import java.io.FileNotFoundException;
    1. import java.io.FileOutputStream;
    1. import java.io.IOException;
    1. import java.util.Random;
    1. import javax.imageio.ImageIO;
    1. import org.junit.Test;
    1. public class Demoimg {
    1. Test
    1. public void Test() throws Exception{
    1. String str=”9988”;
    1. int width=60;
    1. int height=30;
    1. //通过bufferedImage对象获得Graphics对象
    1. BufferedImage bfi=new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
    1. Graphics g=bfi.getGraphics();
    1. g.drawString(str, 10,10);
    1. g.dispose();//类似于IO中的关流
    1. ImageIO.write(bfi , “JPEG”, new FileOutputStream(“F:\ex\a.jpg”));
    1. //bfi为画布,将画布写到文件中JPEG为指定文件格式
    1. }
    1. Test
    1. public void Test2() throws Exception{
    1. int width=100;
    1. int height=40;
    1. BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    1. Graphics g=bfi.getGraphics();//获得Graphics对象就可以画图
    1. //1,设置背景(白框框)
    1. g.setColor(Color.WHITE);//白色的画笔
    1. g.fillRect(0, 0, width, height);
    1. //2,具体生成随机数
    1. String str=””;//保存数据
    1. Random rom=new Random();
    1. //设置字体的大写与粗
    1. g.setFont(new Font(“a”, Font.BOLD,20));
    1. //画出具体的图片
    1. for(int i=0;i<4;i++){
    1. int num=rom.nextInt(10);//生成的随机数
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawString(“”+num, 20*i, 20+rom.nextInt(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下
    1. //PS:位置需要明确些,
    1. }
    1. //画出一些干扰线
    1. for (int i = 0; i < 10; i++) {
    1. g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//设置画笔的颜色(随机)
    1. g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是随机,x,y的值不要超过矩形框框
    1. }
    1. g.dispose();
    1. ImageIO.write(bfi, “JPEG”, new FileOutputStream(“F:\ex\b.jpg”));
    1. }
    1. //画出可以变化的情况
    1. //字体能够旋转的验证码
    1. Test
    1. public void Test3() throws IOException{
    1. int width=100;
    1. int height=40;
    1. BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    1. Graphics g=bfi.getGraphics();
    1. Graphics2D g2d=(Graphics2D) g;
    1. Random rom =new Random();
    1. g2d.setColor(Color.WHITE);//设置画笔的颜色
    1. g2d.fillRect(0, 0, width, height);//画出一个白色的矩形
    1. g2d.setFont(new Font(“a”, Font.BOLD, 20));
    1. for(int i=0;i<4;i++){
    1. int num=rom.nextInt(10);
    1. //旋转,放缩
    1. AffineTransform aff=new AffineTransform();
    1. //aff.rotate(Math.random(), i*18, height-20);//旋转
    1. aff.scale(0.6+Math.random(), 0.6+Math.random());//缩放
    1. g2d.setColor(new Color(rom.nextInt(256),rom.nextInt(256),rom.nextInt(256)));
    1. g2d.setTransform(aff);
    1. g2d.drawString(“”+num, i*18, height-25);
    1. }
    1. g2d.dispose();
    1. ImageIO.write(bfi, “JPEG”, new FileOutputStream(“F:\ex\c.jpg”));
    1. }
    1. }

    已使用 Microsoft OneNote 2016 创建。