zoukankan      html  css  js  c++  java
  • java验证码工具

    工具类:

    package com.lhy.web.servlet;
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    
    public class VerifyCode {
        
        private int w = 70;//图片长
        
        private int h = 35;//图片宽
        
         private Random r = new Random();//Random类 生成随机数
         
         // 列举验证图片中验证码的字体类型
         //{"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"}
        private String[] fontNames  = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
        // 验证码可选字符
        private String codes="23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
        // 背景色
        private Color bgColor  = new Color(255, 255, 255);
        // 验证码上的文本
        private String text ;
        
        
        // 生成随机的颜色
        private Color randomColor () {
                int red = r.nextInt(150);
                int green = r.nextInt(150);
                int blue = r.nextInt(150);
                return new Color(red, green, blue);
        }
        // 生成随机的字体
        private Font randomFont () {
                    int index = r.nextInt(fontNames.length);
                    String fontName = fontNames[index];//生成随机的字体名称
                    int style = r.nextInt(4);//生成随机的样式, 0(无样式), 1(粗体), 2(斜体), 3(粗体+斜体)
                    int size = r.nextInt(5) + 24; //生成随机字号, 24 ~ 28
                    return new Font(fontName, style, size);
        }
        // 画干扰线
        private void drawLine (BufferedImage image) {
                int num  = 3;//一共画3条
                Graphics2D g2 = (Graphics2D)image.getGraphics();
                for(int i = 0; i < num; i++) {//生成两个点的坐标,即4个值
                    int x1 = r.nextInt(w);
                    int y1 = r.nextInt(h);
                    int x2 = r.nextInt(w);
                    int y2 = r.nextInt(h); 
                    g2.setStroke(new BasicStroke(1.5F)); 
                    g2.setColor(Color.BLUE); //干扰线是蓝色
                    g2.drawLine(x1, y1, x2, y2);//画线
                }
        }
        
        // 随机生成一个字符
        private char randomChar () {
                int index = r.nextInt(codes.length());
                return codes.charAt(index);
        }
        
        // 创建BufferedImage
        private BufferedImage createImage () {
                //宽,高,图片的类型
                BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
                Graphics2D g2 = (Graphics2D)image.getGraphics(); 
                g2.setColor(this.bgColor);
                g2.fillRect(0, 0, w, h);
                 return image;
        }
        
        // 返回验证码图片上的文本
        public String getText () {
                return text;
        }
        
        // 保存图片到指定的输出流
        public static void output (BufferedImage image, OutputStream out) 
                        throws IOException {
                ImageIO.write(image, "JPEG", out);
        }
        
        // 调用这个方法得到验证码
            public BufferedImage getImage () {
                    BufferedImage image = createImage();//创建图片缓冲区 
                    Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境
                    StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
                    // 向图片中画4个字符
                    for(int i = 0; i < 4; i++)  {//循环四次,每次生成一个字符
                        String s = randomChar() + "";//随机生成一个字母 
                        sb.append(s); //把字母添加到sb中
                        float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
                        g2.setFont(randomFont()); //设置随机字体
                        g2.setColor(randomColor()); //设置随机颜色
                        g2.drawString(s, x, h-5); //画图
                    }
                    this.text = sb.toString(); //把生成的字符串赋给了this.text
                    drawLine(image); //添加干扰线
                    return image;        
            }
    
    
            public static void main(String[] args) throws FileNotFoundException, IOException {
                VerifyCode vc = new VerifyCode();//创建VerifyCode类的对象
                BufferedImage bi = vc.getImage();//调用getImge()方法获得一个BufferedImage对象
                VerifyCode.output(bi, new FileOutputStream("C:/验证码3.jpg"));//调用静态方法output()方法将图片保存在文件输出流中
                System.out.println(vc.getText());//在控制台上打印验证码的文本值
            }
    
    }

    VerifyCodeServlet:

    package com.lhy.web.servlet;
    
    import java.awt.image.BufferedImage;
    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 VerifyCodeServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            /*
             * 1. 生成图片
             * 2. 保存图片上的文本到session域中
             * 3. 把图片响应给客户端
             */
            VerifyCode vc = new VerifyCode();
            BufferedImage image = vc.getImage();
            request.getSession().setAttribute("session_vcode", vc.getText());//保存图片上的文本到session域
            
            VerifyCode.output(image, response.getOutputStream());
        }
    
    }

    LoginServlet:

    package com.lhy.web.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    public class LoginServlet extends HttpServlet {
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            /*
             * 校验验证码
             * 1. 从session中获取正确的验证码
             * 2. 从表单中获取用户填写的验证码
             * 3. 进行比较!
             * 4. 如果相同,向下运行,否则保存错误信息到request域,转发到login.jsp
             */
            String sessionCode = (String) request.getSession().getAttribute("session_vcode");
            String paramCode = request.getParameter("verifyCode");
            
            if(!paramCode.equalsIgnoreCase(sessionCode)) {
                request.setAttribute("msg", "验证码错误!");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
                return;
            }
            /*
             * 1. 获取表单数据
             */
            // 处理中文问题
            request.setCharacterEncoding("utf-8");
            // 获取
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            /*
             * 2. 校验用户名和密码是否正确
             */
            if("itcast".equalsIgnoreCase(username)) {//登录成功
                /*
                 * 附加项:把用户名保存到cookie中,发送给客户端浏览器
                 * 当再次打开login.jsp时,login.jsp中会读取request中的cookie,把它显示到用户名文本框中
                 */
                Cookie cookie = new Cookie("uname", username);//创建Cookie
                cookie.setMaxAge(60*60*24);//设置cookie命长为1天
                response.addCookie(cookie);//保存cookie
                
                /*
                 * 3. 如果成功
                 *   >  保存用户信息到session中
                 *   >  重定向到succ1.jsp
                 */
                HttpSession session = request.getSession();//获取session
                session.setAttribute("username", username);//向session域中保存用户名
                response.sendRedirect("/Test/succ1.jsp");
            } else {//登录失败
                /*
                 * 4. 如果失败
                 *   > 保存错误信息到request域中
                 *   > 转发到login.jsp
                 */
                request.setAttribute("msg", "用户名或密码错误!");
                RequestDispatcher qr = request.getRequestDispatcher("/login.jsp");//得到转发器
                qr.forward(request, response);//转发
            }
        }
        }

    login.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 'login.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">
        -->
    <script type="text/javascript">
    function _change() {
        /*
        1. 得到img元素
        2. 修改其src
        */
        var imgEle = document.getElementById("img");
        imgEle.src = "<%=basePath%>servlet/VerifyCodeServlet?a=" + new Date().getTime();
    }
    </script>
      </head>
      
      <body>
    <%-- 本页面提供登录表单,还要显示错误信息 --%>
    
    <h1>登录</h1>
     
    <%
    /*
    读取名为uname的Cookie!
    如果为空显示:""
    如果不为空显示:Cookie的值
    */
    String uname = "";
    Cookie[] cs = request.getCookies();//获取请求中所有的cookie
    if(cs != null) {// 如果存在cookie
        for(Cookie c : cs) {//循环遍历所有的cookie
            if("uname".equals(c.getName())) {//查找名为uname的cookie
                uname = c.getValue();//获取这个cookie的值,给uname这个变量
            }
        }
    }
    %>
    <%
        String message = "";
        String msg = (String)request.getAttribute("msg");//获取request域中的名为msg的属性
        if(msg != null) {
            message = msg;
        }
    %>
    <font color="red"><b><%=message %> </b></font>
    <form action="servlet/LoginServlet" method="post">
                <%-- 把cookie中的用户名显示到用户名文本框中 --%>
        用户名:<input type="text" name="username" value="<%=uname%>"/><br/>
        密 码:<input type="password" name="password"/><br/>
        验证码:<input type="text" name="verifyCode" size="3"/>
                <img id="img" src="<%=basePath%>servlet/VerifyCodeServlet"/>
                <a href="javascript:_change()">换一张</a>
                <br/>
        <input type="submit" value="登录"/>
    </form>
    
      </body>
    </html>

    loginsuccess:

    <body>
    <h1>succ1</h1>
    <%
    String username = (String)session.getAttribute("username");
    if(username == null) {
        /*
        1. 向request域中保存错误信息,转发到login.jsp
        */
        request.setAttribute("msg", "您还没有登录!请先登录!");
        request.getRequestDispatcher("/login.jsp").forward(request, response);
        return;
    }
    %>
    
    欢迎欢迎,热烈欢迎,欢迎<%=username %>领导指导工作!
      </body>
    </html>

    配置文件:

     <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.lhy.web.servlet.LoginServlet</servlet-class>
      </servlet>
       <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/servlet/LoginServlet</url-pattern>
      </servlet-mapping>
      
      <servlet>
        <servlet-name>VerifyCodeServlet</servlet-name>
        <servlet-class>com.lhy.web.servlet.VerifyCodeServlet</servlet-class>
      </servlet>
       <servlet-mapping>
        <servlet-name>VerifyCodeServlet</servlet-name>
        <url-pattern>/servlet/VerifyCodeServlet</url-pattern>
      </servlet-mapping>
      

    建议:生成验证码的Servlet最好设置成不缓存,这样就不用再页面请求验证码图片的时候加上时间戳了,加上时间戳就是欺骗浏览器防止浏览器读取缓存里的验证码图片,而点击换一张后没反应。 这样的不是很好的一点就是,每次点击换一张,浏览器都会把新获取的图片缓存到本地,而在Servlet里设置不缓存,就不会缓存到本地了。

  • 相关阅读:
    Effective Java:Ch4_Class:Item14_在public类中应该使用访问方法而不是public域
    [置顶] 学习JDK源码:可进一步优化的代码
    [置顶] 学习JDK源码:编程习惯和设计模式
    如何开展软件架构之概念架构
    POJ 3667 & 1823 Hotel (线段树区间合并)
    CF 161D Distance in Tree【树DP】
    BroadcastReceiver基础总结
    OSI七层模型具体解释
    习惯的力量之四理直气壮的借口?
    堆(stack) 之 c 和 c++模板实现(空类默认成员函数 初谈引用 内联函数)
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/7131512.html
Copyright © 2011-2022 走看看