网页验证码的动态生成

今天介绍两种方式:一个是servlet实现另一个直接是jsp实现(毕竟jsp中可以写Java代码)
方式一:jsp实现验证码的生成

<%@ page language="java" contentType="text/html;charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Random"%>
<%@ page import="java.io.OutputStream"%>
<%@ page import="java.awt.Color"%>
<%@ page import="java.awt.Font"%>
<%@ page import="java.awt.Graphics"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.imageio.ImageIO"%>
<%
    Random rand = new Random();
    //创建图像
    int width = 90;
    int height = 30;
    BufferedImage image = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_RGB);
    //获得画笔对象
    Graphics g = image.getGraphics();
    //画黑色的边框背景色为草绿色
    g.setColor(Color.BLACK);
    g.fillRect(0, 0, width, height);
    g.setColor(Color.GREEN);
    g.fillRect(1, 1, width - 2, height - 2);
    //制造背景混淆
    g.setColor(Color.YELLOW);
    for (int i = 0; i < 1000; i++) {
        g.drawOval(rand.nextInt(width), rand.nextInt(height), 1, 1);
    }
    //填充内容汉子或者字母:字符错开并且可以带各自的效果
    Color c[] = new Color[] { Color.RED, Color.BLUE, Color.GRAY,
            Color.BLACK };
    g.setFont(new Font("宋体", Font.BOLD + Font.ITALIC, 22));
    String words = "徽省合市阳区中铁际啦倒IloveYOUveryMUch";
    words="\u5fbd\u7701\u5408\u5e02\u9633\u533a\u4e2d\u94c1\u9645\u5566\u5012IloveYOUveryMUch";
    for (int i = 0; i < 4; i++) {
        int flag = rand.nextBoolean() ? 1 : -1;
        g.setColor(c[rand.nextInt(c.length)]);
        g.drawString(words.charAt(rand.nextInt(words.length())) + "",
                15 + 15 * i + flag * rand.nextInt(5),
                20 + flag * rand.nextInt(5));
    }
    g.dispose();
    //下面这三句解决了报多个输出流异常
    response.setContentType("image/jpeg");
    out.clear();
    out = pageContext.pushBody();
    //因为jsp已经有了out(JspWriter)所以这里就会包异常illegalStateException,不过对界面的显示没有影响
    ServletOutputStream sos = response.getOutputStream();
    ImageIO.write(image, "jpeg", sos);
    sos.close();
%>

给新建一个上面这样的jsp文件即可;
方式二:servlet实现验证码

package com.zbv.authcode;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AuthCodeServlet extends HttpServlet {
    /**
     * The doGet method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to get.
     * 
     * @param request the request send by the client to the server
     * @param response the response send by the server to the client
     * @throws ServletException if an error occurred
     * @throws IOException if an error occurred
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //response.getWriter()和response.getOutputStream()只能使用一个
//      PrintWriter out=response.getWriter();
        //不需要缓存三种代码
        response.setHeader("Expires", -1+"");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        Random rand=new Random();
        //创建图像
        int width=90;
        int height=30;
        BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获得画笔对象
        Graphics g=image.getGraphics();
        //画黑色的边框背景色为草绿色
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, width, height);
        g.setColor(Color.GREEN);
        g.fillRect(1, 1, width-2, height-2);
        //制造背景混淆
        g.setColor(Color.YELLOW);
        for(int i=0;i<1000;i++){
            g.drawOval(rand.nextInt(width), rand.nextInt(height), 1, 1);
        }
        //填充内容汉子或者字母:字符错开并且可以带各自的效果
        Color c[]=new Color[]{Color.RED,Color.BLUE,Color.GRAY,Color.BLACK};
//      g.setColor(Color.RED);
        //此处注意字体必须设置,还有字体类型如果是需要显示中文还要挑对字体类型不然显示不出来的哦
        //tips:转化Unicode编码两种简便方式:方式一:使用jdk自带的native2ascii 其次就是使用eclipse建立properties文件可以得到
        g.setFont(new Font("宋体", Font.BOLD+Font.ITALIC, 22));
        String words="徽省合市阳区中铁际啦倒IloveYOUveryMUch";
    //\u5fbd\u7701\u5408\u5e02\u9633\u533a\u4e2d\u94c1\u9645\u5566\u5012IloveYOUveryMUch
        //转换成Unicode编码
    words="\u5fbd\u7701\u5408\u5e02\u9633\u533a\u4e2d\u94c1\u9645\u5566\u5012IloveYOUveryMUch";
//      StringBuffer toShow = new StringBuffer();
//      String show ="";
        for(int i=0;i<4;i++){
//          int n=rand.nextInt(words.length());
//          g.drawString(n+"", 20+20*i, 20);
//          show+=words.charAt(rand.nextInt(words.length()));
//          toShow.append(words.charAt(rand.nextInt(words.length())));
            int flag=rand.nextBoolean()?1:-1;
            g.setColor(c[rand.nextInt(c.length)]);
            //这样设定是为了随机的高度上下有偏差以及左右的间隔也有偏差甚至会重叠一部分
            g.drawString(words.charAt(rand.nextInt(words.length()))+"", 15+15*i+flag*rand.nextInt(5), 20+flag*rand.nextInt(5));
        }
//      System.err.println(show);
        //这样做就是去Unicode编码作用了....
//      g.drawString(toShow.toString(), width, height);
        //注意这个10 15相对于该image而言的
//      g.drawString(show, 10, 15);
        //释放系统资源
        g.dispose();
        ServletOutputStream sos=response.getOutputStream();
        ImageIO.write(image, "jpeg", sos);
        sos.close();
    }
    /**
     * The doPost method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to post.
     * 
     * @param request the request send by the client to the server
     * @param response the response send by the server to the client
     * @throws ServletException if an error occurred
     * @throws IOException if an error occurred
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

以上便是要新建一个servlet;
具体显示jsp页面如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
    <style>
    *{
    margin:20px;
    padding:0px;
    }
    .container{
    width:1000px;
    height:300px;
    margin:0px auto;
    text-align:center;
    }
    .container img{
    -webkit-filter:grayscale(50%);
    filter:grayscale(50%);
    }
    .container a{
    text-decoration:none;
    float:right;
    }
    .container a:hover{
    text-decoration:underline;
    }
    </style>
    <script>
    function onReFetch(){
        var img=document.getElementById("verification_code");
        //解决浏览器缓存img的问题
        //img.src="/AuthCodeTest/servlet/AuthCodeServlet?"+new Date().getTime();
        img.src="/AuthCodeTest/AuthCodeUtil.jsp?"+Math.random();
    }
    </script>
  </head>

  <body>
    <div class="container">
    <!-- <img src="${pageContext.request.contextPath}/servlet/AuthCodeServlet" id="verification_code"></img> -->
    <img src="${pageContext.request.contextPath}/AuthCodeUtil.jsp" id="verification_code"></img>
    <a href="javascript:onReFetch()">重新获取验证码</a>
    <div>
  </body>
</html>

老习惯啦,最后说一下:
网页验证码的设计可能在你很多需要登录注册的网站都会遇到,算是web的一个简单的知识点吧,今天分享出来共同学习学习挺好的。分享是一种快乐,共同进步才是王道。以飨喜欢的小伙伴们^–^
当然,非常欢迎大神给予错误的纠正以及提升的建议,谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值