您的位置:首页 > 理论基础 > 计算机网络

关于<验证码>的实现和执行流程 http://www.cnblogs.com/android-html5/archive/2012/05/19/2533650.html

2012-12-21 16:33 811 查看
验证码是一个很常见的一个功能,验证码可以防止黑客通过某种手段无间隔的注册等等

验证码是通过服务器端生成的一张图片,传到客户端

具体实现步骤(流程):

1)由服务器端比如servlet,随机产生几个字符数字等等,把这几个字符拼接成一个字符串,存到session域中

2)以图片的方式传给客户端,验证码上的具体值是在服务器端验证的,如果具体值在客户端验证的话,恐怕不太方便比如第一次访问静态登录界面的话,去取session的值是为空的,除非你再次刷新整个页面

3)客户端对验证码,验证是否为空,输入的字符的长度是否达到标准,

4)把输入的验证码传到服务器端,服务端在session中取到值,做具体判断

5)根据输入对否,跳转到另一界面,如果输入错误,一般跳回当前界面,验证码改变又被刷新一次

具体实现的页面:

产生验证码的 Response_3类 参考-------->点击打开链接

package cn.response;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//输出随机认证码图片
public class Response_3 extends HttpServlet {

private static final int WIDTH=120, HEIGHT=50;

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

//创建一幅图形
BufferedImage image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();

//1.设置背景色
setBackGround(g);

//2.设置边框
setBorder(g);

//3.画干扰线
drawRandomLine(g);

//4.写随机数  返回  具体的验证值
String validateValue = drawRandomNum((Graphics2D)g);
System.out.println("验证码:"+validateValue);
//把验证码的具体值 存到session中
request.getSession().setAttribute("validateValue", validateValue);

//5.图形写给浏览器

//控制浏览器缓存      System.currentTimeMillis() 获取当前时间
//response.setDateHeader("Expires",System.currentTimeMillis() + 1000*3600); //缓存1小时

//控制浏览器不要缓存数据
response.setDateHeader("Expires", -1);
response.setHeader("cache-control", "no-cache");
response.setHeader("pragma", "no-cache");

response.setContentType("image/jpeg");//告诉浏览器用什么方式打开
//把图形以JPG的格式存到流中然后调用 ImageIO.write输到浏览器
ImageIO.write(image,"jpg",response.getOutputStream());

}

private void setBackGround(Graphics g)
{
g.setColor(Color.lightGray);//设置背景色
g.fillRect(0, 0, WIDTH, HEIGHT);//让颜色去填充这个矩形

}

private void setBorder(Graphics g)
{
//设置边框的颜色 随机出现
if(0 == new Random().nextInt(3))
{
g.setColor(Color.cyan);//设置边框颜色
}
else if(1 == new Random().nextInt(5))
{
g.setColor(Color.red);//设置边框颜色
}
else
{
g.setColor(Color.yellow);//设置边框颜色
}

g.drawRect(1, 1, WIDTH-2, HEIGHT-2);//绘制边框
}

private void drawRandomLine(Graphics g)
{
g.setColor(Color.green);
for(int i=0; i<5; i++)
{
//随机获得初始坐标,和结束坐标
int x1 = new Random().nextInt(WIDTH);//横坐标要在宽度之内
int y1 = new Random().nextInt(HEIGHT);//纵坐标要在高度之内
int x2 = new Random().nextInt(WIDTH);
int y2 = new Random().nextInt(HEIGHT);

g.drawLine(x1, y1, x2, y2);//画干扰线
}
}

private String drawRandomNum(Graphics2D g)
{
String validateValue = "" ; // 具体验证码的值

g.setColor(Color.red);
g.setFont(new Font("宋体",Font.BOLD,28));//设置字体

//汉字
//String base="\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09";
String base= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz" ;
int x=5;
//中文字体范围 [\u4e00-\u9fa5]
for(int i=0; i<4; i++)
{
int theta = new Random().nextInt()%30;//获取-30到30的数
//String x1 = new Random().nextInt(9)+""; 随机输出数字
String ch = base.charAt( new Random().nextInt(base.length()) )+"";//获取字

g.rotate(theta*Math.PI/180, x, 30);//设置旋转角度(弧度)
g.drawString(ch, x, 30);//写字到方框内

g.rotate(-theta*Math.PI/180, x, 30);//把位置旋转回去
//g.drawString(x1, x, 20);
x+=30;
//g.drawString(x1, x, 20);
//x+=30;
validateValue = validateValue + ch ;
}

return validateValue;
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

}

}


Myeclipse 环境下

这里当然还要在WEB-INF目录下,配一个web.xml

总结:

控制浏览器要缓存:

response.setDateHeader("Expires",System.currentTimeMillis() + 1000*3600);注意:如果这句没添加 System.currentTimeMillis() 则没有缓存截止日期,默认是 1970年开始 缓存1小时,也就是过期了,所以System.currentTimeMillis() 这句的作用是获取当前日期时间,然后加上你要缓存的时间,1000代表1秒。

控制浏览器不要缓存:

response.setDateHeader("Expires", -1); 或者 response.setDateHeader("Expires", 0); 都一样

response.setHeader("cache-control", "no-cache");

response.setHeader("pragma", "no-cache");

这里设置了颜色,别忘了设置 把颜色填充,绘制边框,等等

绘制边框:g.drawRect(1, 1, WIDTH-2, HEIGHT-2);// 边框的宽和高,都要比背景色的宽高小1,这个边框是从x=1,y=1 (起使坐标(1,1) )开始画的,本来是从x=0,y=0画的,但贴近最左边效果不好所以WIDTH-2, HEIGHT-2 要减2

中文字体范围 [\u4e00-\u9fa5]

获取随机字符:String ch = base.charAt( new Random().nextInt(base.length()) )+"";

然后把字符转化为字符串

注意: 设置字的旋转角度,g.rotate(theta*Math.PI/180, x, 20);//设置旋转角度(一定要是弧度),把度转化为弧度(公式:theta*Math.PI/180 ;这个theta是度):int theta = new Random().nextInt()%30;//获取-30到30的数,

当你旋转完,把字放到方框里去后,还得注意一点就是把旋转角度,旋转为初始状态,以便下一个字进行旋转

<%@ 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 'ValidateLogin.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">
-->

</head>

<BODY style="background-color:66CCFF" >
<table cellspacing="10"
border=1 background="" align="center">
<tr>
<td>

<b  style="font-size:20;color:green;" >会员--登录</b>
<hr width=220 align=left>

<form name=form1 Action="LoginServlet" method="get"  >

<br />
用户名:
<input type="text" name="usename" value=543806053@qq.com size=19 maxlength=16 />
<br />
<br />
密  码:
<input type="password" name="password" maxlength=16 />
<br /><br />
认证码: <input type="text" name="validateValue" size=19  onblur="checkVlidte(this)"/><br>

<img id="image" src="servlet/Response_3"/>
<a href="javascript:changeimage()" >看不清?换一张</a>
<br /><br />

<br /><br />
<input type="submit" value="登录"/>
<input type="reset" value="重置" />
<hr width=220 align=left>
</form>
</td>
</tr>

</table>

</body>

<script type="text/javascript">
function validate_required(field,alerttxt)
{
with(field)
{

/*if(value==null||value=="")
{
alert(alerttxt);
return false ;
}
else
return true ;
*/

i = value.indexOf("@");  //邮箱认证
j = value.lastIndexOf(".");
if(i < 1 || j-i <2)
{
alert(alerttxt) ;
return false ;
}
else
return true ;
}
}

function password_validate (_pass,alerttxt)
{
with(_pass)
{
if(value!="")
return true ;
else
{
alert(alerttxt) ;
return false ;
}
}
}

function validate_form(thisform)
{
with(thisform)
{
if(validate_required(name1,"请输入有效的邮箱账号!") == false)
{
name1.focus();
return false ;
}

if(password_validate(pass,"请输入正确的密码!") == false)
{
pass.focus();
return false ;
}

}
}

</script>

<script type="text/javascript">

function proving()
{
if(form1.pass.value!="")
window.open("http://www.baidu.com/","_self");
else
window.open("http://www.google.com/","_self");

}

</script>

<!--认证码按钮脚本-->
<script type="text/javascript">
function changeimage()
{
var img = document.getElementById("image") ;
if(img)
img.src=img.src+ "?" + new Date().getTime();
}

function checkVlidte(object)
{

if(object.value.length != 4 )
{
alert("验证码错误!");

//object.focus() ;//重新定位到该输入框
//object.select() ;//把已有的内容选中
}
}

</script>

</html>


服务器端验证,这里只对验证码进行验证

package cn.request;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//主要 服务器端验证码 的验证
public class LoginServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

this.doPost(request, response);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String usename = request.getParameter("usename");
String password = request.getParameter("password");
String validateValue = request.getParameter("validateValue");

String vv = (String)request.getSession().getAttribute("validateValue");

//把验证码全转为小写在进行比较
if( (validateValue.toLowerCase()).equals(vv.toLowerCase()) )
{
response.sendRedirect("index.jsp");
}
else
{
request.getRequestDispatcher("ValidateLogin.jsp").forward(request, response);
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐