验证码基础
一.什么是验证码及它的作用
:验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。
二.图文验证码的原理
:在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。
三.验证码所需的技术
:i.因为验证码中的文字,数字,应为都是可变的,故要用到随机生成数技术。
ii.如果验证码中包含汉字,则要用到汉字生成技术.
iii.可以使用Ajax技术实现局部刷新
iv.可以使用图片的缩放和旋转技术,
vi.随机绘制干扰线(可以是折现,直线等)
vii.如果考虑到验证码的安全性,可以使用MD5加密.
验证码模块实例
1.编写生成英文,数字,汉字随机生成的Servlet类.源代码如下:
- package com.servlet;
-
- import java.awt.*;
- import java.awt.geom.*;
- import java.awt.image.*;
- import java.io.*;
- import java.util.*;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import javax.imageio.ImageIO;
-
- public class PictureCheckCode extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
-
- public PictureCheckCode() {
- super();
- }
-
- public void destroy() {
- super.destroy();
- }
-
- public void init() throws ServletException {
- super.init();
- }
-
- public Color getRandColor(int s,int e){
- Random random=new Random ();
- if(s>255) s=255;
- if(e>255) e=255;
- int r,g,b;
- r=s+random.nextInt(e-s);
- g=s+random.nextInt(e-s);
- b=s+random.nextInt(e-s);
- return new Color(r,g,b);
- }
-
- @Override
- public void service(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=86,height=22;
- BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
- Graphics g=image.getGraphics();
- Graphics2D g2d=(Graphics2D)g;
- Random random=new Random();
- Font mfont=new Font("楷体",Font.BOLD,16);
- g.setColor(getRandColor(200,250));
- g.fillRect(0, 0, width, height);
- g.setFont(mfont);
- g.setColor(getRandColor(180,200));
-
-
- for(int i=0;i<100;i++){
- int x=random.nextInt(width-1);
- int y=random.nextInt(height-1);
- int x1=random.nextInt(6)+1;
- int y1=random.nextInt(12)+1;
- BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);
- Line2D line=new Line2D.Double(x,y,x+x1,y+y1);
- g2d.setStroke(bs);
- g2d.draw(line);
- }
-
- String sRand="";
- String ctmp="";
- int itmp=0;
-
- for(int i=0;i<4;i++){
- switch(random.nextInt(3)){
- case 1:
- itmp=random.nextInt(26)+65;
- ctmp=String.valueOf((char)itmp);
- break;
- case 2:
- String[] rBase={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
-
- int r1=random.nextInt(3)+11;
- String str_r1=rBase[r1];
-
- int r2;
- if(r1==13){
- r2=random.nextInt(7);
- }else{
- r2=random.nextInt(16);
- }
- String str_r2=rBase[r2];
-
- int r3=random.nextInt(6)+10;
- String str_r3=rBase[r3];
-
- int r4;
- if(r3==10){
- r4=random.nextInt(15)+1;
- }else if(r3==15){
- r4=random.nextInt(15);
- }else{
- r4=random.nextInt(16);
- }
- String str_r4=rBase[r4];
-
- byte[] bytes=new byte[2];
-
- String str_12=str_r1+str_r2;
- int tempLow=Integer.parseInt(str_12, 16);
- bytes[0]=(byte) tempLow;
-
- String str_34=str_r3+str_r4;
- int tempHigh=Integer.parseInt(str_34, 16);
- bytes[1]=(byte)tempHigh;
- ctmp=new String(bytes);
- break;
- default:
- itmp=random.nextInt(10)+48;
- ctmp=String.valueOf((char)itmp);
- break;
- }
- sRand+=ctmp;
- Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));
- g.setColor(color);
-
-
- Graphics2D g2d_word=(Graphics2D)g;
- AffineTransform trans=new AffineTransform();
- trans.rotate((45)*3.14/180,15*i+8,7);
-
- float scaleSize=random.nextFloat()+0.8f;
- if(scaleSize>1f) scaleSize=1f;
- trans.scale(scaleSize, scaleSize);
- g2d_word.setTransform(trans);
- g.drawString(ctmp, 15*i+18, 14);
- }
- HttpSession session=request.getSession(true);
- session.setAttribute("randCheckCode", sRand);
- g.dispose();
- ImageIO.write(image,"JPEG",response.getOutputStream());
- }
- }
2.配置Servlet
在web.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:
- http:
- <servlet>
- <description>输出验证码</description>
- <display-name>This is the display name of my J2EE component</display-name>
- <servlet-name>PictureCheckCode</servlet-name>
- <servlet-class><SPAN style="COLOR: #ff0000">com.servlet.PictureCheckCode</SPAN></servlet-class>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>PictureCheckCode</servlet-name>
- <url-pattern>/<SPAN style="COLOR: #ff0000">PictureCheckCode</SPAN></url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
3.测试验证码
可以编写JSP页面来验证是否可以输出验证码图片,JSP代码如下:
1.index.jsp:显示界面
- <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>验证码</title>
- <script language="javascript">
- function myReload() {
- document.getElementById("CreateCheckCode").src = document
- .getElementById("CreateCheckCode").src
- + "?nocache=" + new Date().getTime();
- }
- </script>
- </head>
-
- <body>
- <form action="Check.jsp" method="post">
- <input name="checkCode" type="text" id="checkCode" title="验证码区分大小写"
- size="8" ,maxlength="4" />
- <img src="PictureCheckCode" id="CreateCheckCode" align="middle">
- <a href="" onclick="myReload()"> 看不清,换一个</a>
- <input type="submit" value="提交" />
- </form>
- </body>
- </html>
2.Check.jsp :主要验证提交的数据是否和Session中保存的验证码是否相同
- <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
- <html>
- <head>
- <title>验证码校验</title>
- </head>
-
- <body>
- <%
- String checkcode=request.getParameter("checkCode");
- if(checkcode.equals("")||checkcode==null){
- out.print("<script>alert('请输入验证码');window.location.href('index.jsp')</script>");
- }else{
- if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){
- out.print("<script>alert('验证码不正确,请重新输入');history.back(-1);</script>");
- }else{
- out.print("登录成功");
- }
- }
- %>
- </body>
- </html>
4.工程项目结构,及运行截图