Java实现验证码验证功能
来源:互联网 发布:柯南帅气 知乎 编辑:程序博客网 时间:2024/05/23 00:01
Java如何实现验证码验证功能呢?日常生活中,验证码随处可见,他可以在一定程度上保护账号安全,那么他是怎么实现的呢?
Java实现验证码验证功能其实非常简单:用到了一个Graphics类在画板上绘制字母,随机选取一定数量的字母随机生成,然后在画板上随机生成几条干扰线。
首先,写一个验证码生成帮助类,用来绘制随机字母:
- <span style="font-size:14px;">import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.Random;
-
- import javax.imageio.ImageIO;
-
- public final class GraphicHelper {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static String create(final int width, final int height, final String imgType, OutputStream output) {
- StringBuffer sb = new StringBuffer();
- Random random = new Random();
-
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- Graphics graphic = image.getGraphics();
-
- graphic.setColor(Color.getColor("F8F8F8"));
- graphic.fillRect(0, 0, width, height);
-
- Color[] colors = new Color[] { Color.BLUE, Color.GRAY, Color.GREEN, Color.RED, Color.BLACK, Color.ORANGE,
- Color.CYAN };
-
- for (int i = 0; i < 50; i++) {
- graphic.setColor(colors[random.nextInt(colors.length)]);
- final int x = random.nextInt(width);
- final int y = random.nextInt(height);
- final int w = random.nextInt(20);
- final int h = random.nextInt(20);
- final int signA = random.nextBoolean() ? 1 : -1;
- final int signB = random.nextBoolean() ? 1 : -1;
- graphic.drawLine(x, y, x + w * signA, y + h * signB);
- }
-
-
- graphic.setFont(new Font("Comic Sans MS", Font.BOLD, 30));
- for (int i = 0; i < 6; i++) {
- final int temp = random.nextInt(26) + 97;
- String s = String.valueOf((char) temp);
- sb.append(s);
- graphic.setColor(colors[random.nextInt(colors.length)]);
- graphic.drawString(s, i * (width / 6), height - (height / 3));
- }
- graphic.dispose();
- try {
- ImageIO.write(image, imgType, output);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return sb.toString();
- }
-
- }
- </span>
接着,创建一个servlet,用来固定图片大小,以及处理验证码的使用场景,以及捕获页面生成的验证码(捕获到的二维码与用户输入的验证码一致才能通过)。- <span style="font-size:14px;">import java.io.IOException;
- import java.io.OutputStream;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
-
- @WebServlet(urlPatterns = "/verify/regist.do" )
- public class VerifyCodeServlet extends HttpServlet {
-
- private static final long serialVersionUID = 3398560501558431737L;
-
- @Override
- protected void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
-
- HttpSession session = request.getSession();
-
-
- String uri = request.getRequestURI();
- System.out.println("hello : " + uri);
-
- final int width = 180;
- final int height = 40;
- final String imgType = "jpeg";
- final OutputStream output = response.getOutputStream();
-
-
- String code = GraphicHelper.create(width, height, imgType, output);
- System.out.println("验证码内容: " + code);
-
-
- session.setAttribute(uri, code);
-
- System.out.println(session.getAttribute(uri));
-
- }
-
- }
- </span>
接着写一个HTML注册页面用来检验一下:- <span style="font-size:14px;"><!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>注册</title>
- <link rel="stylesheet" href="styles/general.css">
- <link rel="stylesheet" href="styles/cell.css">
- <link rel="stylesheet" href="styles/form.css">
- <script type="text/javascript" src="js/ref.js"></script>
- <style type="text/css" >
-
- .logo-container {
- margin-top: 50px ;
- }
- .logo-container img {
- width: 100px ;
- }
-
- .message-container {
- height: 80px ;
- }
-
- .link-container {
- height: 40px ;
- line-height: 40px ;
- }
-
- .link-container a {
- text-decoration: none ;
- }
-
- </style>
-
- </head>
- <body>
- <div class="container form-container">
- <form action="/wendao/regist.do" method="post">
- <div class="form">
-
- <div class="form-row">
- <span class="cell-1">
- <i class="fa fa-user"></i>
- </span>
- <span class="cell-11" style="text-align: left;">
- <input type="text" name="username" placeholder="请输入用户名">
- </span>
- </div>
-
- <div class="form-row">
- <span class="cell-1">
- <i class="fa fa-key"></i>
- </span>
- <span class="cell-11" style="text-align: left;">
- <input type="password" name="password" placeholder="请输入密码">
- </span>
- </div>
-
- <div class="form-row">
- <span class="cell-1">
- <i class="fa fa-keyboard-o"></i>
- </span>
- <span class="cell-11" style="text-align: left;">
- <input type="password" name="confirm" placeholder="请确认密码">
- </span>
- </div>
-
- <div class="form-row">
- <span class="cell-7">
- <input type="text" name="verifyCode" placeholder="请输入验证码">
- </span>
- <span class="cell-5" style="text-align: center;">
- <img src="/demo/verify/regist.do" onclick="myRefersh(this)">
- </span>
- </div>
-
- <div class="form-row" style="border: none;">
- <span class="cell-6" style="text-align: left">
- <input type="reset" value="重置">
- </span>
- <span class="cell-6" style="text-align:right;">
- <input type="submit" value="注册">
- </span>
- </div>
-
- </div>
- </form>
- </div>
-
- </body>
- </html></span>
效果如下图:在控制台接收到的图片中验证码的变化如下:
当点击刷新页面的时候,验证码也会随着变化,但我们看不清验证码时,只要点击验证码就会刷新,这样局部的刷新可以用JavaScript来实现。在<img src="/demo/verify/regist.do">中,添加一个问号和一串后缀数字,当刷新时让后缀数字不断改变,那么形成的验证码也会不断变化,我们可以采用的一种办法是后缀数字用date代替,date获取本机时间,时间是随时变的,这样就保证了刷新验证码可以随时变化。
代码如下:
- <span style="font-size:14px;">function myRefersh( e ) {
-
- const source = e.src ;
-
-
- var index = source.indexOf( "?" ) ;
-
-
- if( index > -1 ) {
- var s = source.substring( 0 , index ) ;
-
-
- var date = new Date();
- var time = date.getTime() ;
- e.src = s + "?time=" + time ;
-
-
- } else {
- var date = new Date();
- e.src = source + "?time=" + date.getTime();
- }
-
- }</span>