jsp-servlet图像验证码-阿里云开发者社区

开发者社区> tony~tian> 正文

jsp-servlet图像验证码

简介: 实现图像验证码类ImageValidateCode: package com.myhome; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import jav
+关注继续查看

实现图像验证码类ImageValidateCode:

package com.myhome;


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
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;
import javax.servlet.http.HttpSession;
/**
 * 防止暴力破解,使用的图像验证码
 * */
public class ImageValidateCode extends HttpServlet 
{


/**
* 实现java.io.Serializable这个接口是为序列化,
* serialVersionUID 用来表明实现序列化类的不同版本间的兼容性。
* 如果你修改了此类, 要修改此值。否则以前用老版本的类序列化的类恢复时会出错。
* 为了在反序列化时,确保类版本的兼容性。序列化时为了保持版本的兼容性,

* 即在版本升级时反序列化仍保持对象的唯一性。
*/
private static final long serialVersionUID = 5403703649596352260L;
//产生随机数
private Random random =new Random();
//定义图形验证码中绘制字符的字体,字体名称,字体样式,字体大小l;如:"Arial Black"或"Fixedsys", Font.CENTER_BASELINE, 18
private final Font mFont=new Font("Arial Black", Font.PLAIN, 24);
//定义验证码的大小,即高度和宽度
private final int IMG_WIDTH=90;
private final int IMG_HEIGHT=25;
//干扰线的数量
private final int LineSize=50;
//产生的随机字符数量
private int stringNum = 4;  
/**
* 获取随机颜色的方法
* */
private Color getRandColor(int fc,int bc)
{
if(fc>255)
{
fc=255;
}
if(bc>255)
{
bc=255;
}
//产生随机的RGB三原色
int r=fc+random.nextInt(bc-fc-16);
int g=fc+random.nextInt(bc-fc-14);
int b=fc+random.nextInt(bc-fc-18);
return new Color(r, g, b);
}
/**
* 获取大、小写字母和数字随机字符串方法
* */
private String getRandString()
{
//Math.random()---random()方法,是返回一个[0,1)的浮点数。

//一般我们是这样运用的,比如我要取一个1~9的随机数int a=(int)(Math.random()*10)注意是是乘上10再转。
//Math.round()方法,round 就是四舍五入,

//math.round(-8.9) -9;math.round(-8.1) -8;math.round(8.9) 9;math.round(8.1) 8
//生成0、1、2的随机数字
int randi=(int) Math.round(Math.random()*2);
//用来存储数据的ASC码
long itmp=0;
//用于存储字符
char ctmp='\u0000';

//以“\u”开头的是一个Unicode码的字符,每一个'\u0000'都代表了一个空格。

//Unicode可同时包含65536个字符,ASCII/ANSI只包含255个字符,实际上是Unicode的一个子集。

//Unicode字符通常用十六进制编码方案表示,范围在'\u0000'到'\uFFFF'之间。

//\u0000到\u00FF表示ASCII/ANSI字符。

//“\u”表示这是一个Unicode值.\u0000代表的应该是NULL,输出控制台是一个空格...
switch(randi)
{
//生成大写字母
case 1:
itmp=Math.round(Math.random()*25+65);//long类型
ctmp=(char) itmp;//char类型
return String.valueOf(ctmp);//String类型
//生成小写字母
case 2:
itmp=Math.round(Math.random()*25+97);
ctmp=(char) itmp;
return String.valueOf(ctmp);
//生成数字
default :
itmp=Math.round(Math.random()*9);
return itmp+"";//将整型数字连接成字符串
}
}
/**
* 绘制随机字符串
* */
private String drawString(Graphics g,String randomString,int i)
{
g.setFont(mFont);//设置字符串字体
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));//设置字符串颜色
String rands=getRandString();
randomString+=rands;
g.translate(random.nextInt(3), random.nextInt(2));//设置画在图片上的文字的x,y坐标,随即偏移值
g.drawString(rands, 18*i+5, 18);//字符间距设置为15px
,使用此图形上下文的当前字体和颜色绘制由指定 string 给定的文本。最左侧字符的基线位于此图形上下文坐标系统的 (x, y) 位置处。即:str - 要绘制的 string。x - x 坐标。y - y 坐标。//从图像左面10个像素个像素(后15*i+10),距上面16个像素的位置开始从左到右的方向输出rands的值。
return randomString;
}
/**
* 绘制干扰线
* */
private void drawLine1(Graphics g)
{
//参数:x1 - 第一个点的 x 坐标。y1 - 第一个点的 y 坐标。x2 - 第二个点的 x 坐标。y2 - 第二个点的 y 坐标。x1和x2是起点坐标,x2和y2是终点坐标
int x=random.nextInt(IMG_WIDTH);
int y=random.nextInt(IMG_HEIGHT);
int x1=random.nextInt(13);
int y1=random.nextInt(15);
g.drawLine(x, y, x+x1, y+y1);
}
private void drawLine2(Graphics g)
{
//参数:x1 - 第一个点的 x 坐标。y1 - 第一个点的 y 坐标。x2 - 第二个点的 x 坐标。y2 - 第二个点的 y 坐标。x1和x2是起点坐标,x2和y2是终点坐标
int x=random.nextInt(IMG_WIDTH);
int y=random.nextInt(IMG_HEIGHT);
int x1=random.nextInt(13);
int y1=random.nextInt(15);
g.drawLine(x, y, x-x1, y-y1);
}
/**
* 图像验证码的生成
* */
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException 
{
System.out.println("验证码开始生成了");
//设置禁止缓存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");//设置输出流内容格式为图片格式
/*禁用IE缓存
* HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。
* 普通报头中的Cache-Control用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。
* 请求时的缓存指令包括:no-cache(用于指示请示或响应消息不能缓存)、no-store、max-age、max-stale、min-fresh、only-if-cached;
* 响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。
* 例:为了指示IE浏览器(客户端)不要缓存页面,服务器端的jsp程序可以编写如下:response.setHeader(“Cache-Control”, “no-cache”);//response.setHeader(“Pragma”, “no-cache”);
* 作用相当于上行代码,通常两者合用Expires实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面,我们可以使用Expires实体报头域指定页面过期时间。
* 例:Expires:Thu,15 Sep 2006 16:23:12 GMTHTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。
* 如:为了让浏览器不要缓存页面,也可以利用Expires实体报关域,设置为0,jsp程序如下:response.setDateHeader(“Expires”, “0”);
* */
//在内存中创建一副图像,宽90像素,高25像素,rgb模式的色彩
BufferedImage image=new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
//在内存中创建一个画笔
Graphics g=image.getGraphics();
//设置画笔颜色
g.setColor(getRandColor(200, 250));
//填充背景色,使用当前的画笔颜色修改图片背景色 
g.fillRect(1, 1, IMG_WIDTH-1, IMG_HEIGHT-1);//4个参数的意思分别为,起始X坐标,起始Y坐标,宽度,高度。
//为图形验证码绘制边框
g.setColor(new Color(155,155,155));
g.drawRect(0, 0, IMG_WIDTH,IMG_HEIGHT);
//生成随机干扰线
g.setColor(getRandColor(110, 133));
for(int i=0;i<=LineSize;i++){
drawLine1(g);
drawLine2(g);
}
//用于保存系统生成的随机字符串
String randomString = "";
//绘制随机字符串
for(int j=0;j<stringNum;j++){
randomString=drawString(g, randomString, j);
}
//获取HttpSesssion对象
HttpSession session=request.getSession(true);
//getSession(true):true: 如果session存在,则返回该session,否则创建一个新的session;false: 如果session存在,则返回该session,否则返回null.
//将随机字符串放入到HttpSession对象中,验证码中的随机数不区分大小写
session.setAttribute("rand", randomString.toLowerCase());
String rands=(String) session.getAttribute("rand");
System.out.println("验证码生成成功"+rands);
System.out.println("验证码生成成功"+randomString.toLowerCase().toString());
//释放画笔对象
g.dispose();
//向输出流中输出图像
ImageIO.write(image, "JPEG", response.getOutputStream());
}
}

jsp界面实现index.jsp和validat.jsp:

 validat.jsp:

<body>
    <img src="checkServlet" /> <a href="validat.jsp" >看不清楚,换张图片</a>
 </body>


index.jsp:

<head>

<script type="text/javascript">

//看不清图片,重新加载一张图像验证码
function reloadVercode(){
document.getElementById("authImg").src="auth.jpg?now="+new Date();
}
</script>
</head>


<body>
    <img src="auth.jpg" id="authImg" /><a href="javascript:void(null)" onclick="reloadVercode()">看不清,换一张</a>

 </body>

web.xml配置:

<!-- 定义图像验证码的servlet  index.jsp配置-->
  <servlet>
  <servlet-name>img</servlet-name>
  <servlet-class>com.myhome.ImageValidateCode</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>img</servlet-name>
  <url-pattern>/auth.jpg</url-pattern>
  </servlet-mapping>
  
  <!-- 定义图像验证码的servlet  validat.jsp配置-->
    <servlet>
    <servlet-name>CheckServlet</servlet-name>
    <servlet-class>com.myhome.ImageValidateCode</servlet-class>
  </servlet>
   <servlet-mapping>
    <servlet-name>CheckServlet</servlet-name>
    <url-pattern>/checkServlet</url-pattern>
  </servlet-mapping>


效果图:

 

其他:

package com.myhome;


public class Test {
/**
* 产生随机字符串
* */
private String getRandomChar()
{
int rand = (int)Math.round(Math.random() * 2);
System.out.println("随机数:"+rand);
long itmp = 0;
char ctmp = '\u0000';
System.out.println("字符:"+ctmp);
switch (rand)
{
case 1:
itmp = Math.round(Math.random() * 25 + 65);
String s1=getType(itmp);
System.out.println(s1+itmp);
ctmp = (char)itmp;
String s2=getType(ctmp);
System.out.println(s2+itmp);
System.out.println(getType(String.valueOf(ctmp))+String.valueOf(ctmp));
return String.valueOf(ctmp);

case 2:
itmp = Math.round(Math.random() * 25 + 97);
System.out.println(itmp);
ctmp = (char)itmp;
System.out.println(ctmp);
System.out.println(String.valueOf(ctmp));
return String.valueOf(ctmp);
default :
itmp = Math.round(Math.random() * 9);
String.valueOf(itmp);
return  itmp + "";
}
}
/**
* 判断对象的类型
* */
private <T> String getType(T t)
{
if(t instanceof String)
{
return "String";
}else if(t instanceof Integer)
{
return "int";
}else if(t instanceof Character)
{
return "char";
}else if(t instanceof Long)
{
return "long";
}else {
return "don't know Type of" +t;
}
}
public static void main(String[] args) 
{
Test t=new Test();
t.getRandomChar();
}
}


 


 


 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
2962 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11631 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10884 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
12076 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
11818 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4660 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
7503 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7365 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
4506 0
+关注
tony~tian
追求完美,追求自由!
122
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载