Java如何实现验证码验证功能

html-css03

Java如何实现验证码验证功能,第1张

Java如何实现验证码验证功能呢?日常生活中,验证码随处可见,他可以在一定程度上保护账号安全,那么他是怎么实现的呢?

Java实现验证码验证功能其实非常简单:用到了一个Graphics类在画板上绘制字母,随机选取一定数量的字母随机生成,然后在画板上随机生成几条干扰线。

首先,写一个验证码生成帮助类,用来绘制随机字母:

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 {

/**

* 以字符串形式返回生成的验证码,同时输出一个图片

*

* @param width

*            图片的宽度

* @param height

*            图片的高度

* @param imgType

*            图片的类型

* @param output

*            图片的输出流(图片将输出到这个流中)

* @return 返回所生成的验证码(字符串)

*/

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 }

// 在 "画板"上生成干扰线条 ( 50 是线条个数)

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()

}

接着,创建一个servlet,用来固定图片大小,以及处理验证码的使用场景,以及捕获页面生成的验证码(捕获到的二维码与用户输入的验证码一致才能通过)。

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()

// 从请求中获得 URI ( 统一资源标识符 )

String uri = request.getRequestURI()

System.out.println("hello : " + uri)

final int width = 180 // 图片宽度

final int height = 40 // 图片高度

final String imgType = "jpeg" // 指定图片格式 (不是指MIME类型)

final OutputStream output = response.getOutputStream() // 获得可以向客户端返回图片的输出流

// (字节流)

// 创建验证码图片并返回图片上的字符串

String code = GraphicHelper.create(width, height, imgType, output)

System.out.println("验证码内容: " + code)

// 建立 uri 和 相应的 验证码 的关联 ( 存储到当前会话对象的属性中 )

session.setAttribute(uri, code)

System.out.println(session.getAttribute(uri))

}

接着写一个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>

效果如下图:

在控制台接收到的图片中验证码的变化如下:

当点击刷新页面的时候,验证码也会随着变化,但我们看不清验证码时,只要点击验证码就会刷新,这样局部的刷新可以用JavaScript来实现。

在<img

src="/demo/verify/regist.do">中,添加一个问号和一串后缀数字,当刷新时让后缀数字不断改变,那么形成的验证码也会不断变化,我们可以采用的一种办法是后缀数字用date代替,date获取本机时间,时间是随时变的,这样就保证了刷新验证码可以随时变化。

代码如下:

function myRefersh( e ) {

const source = e.src  // 获得原来的 src 中的内容

//console.log( "source : " + source  ) 

var index = source.indexOf( "?" )   // 从 source 中寻找 ? 第一次出现的位置 (如果不存在则返回 -1 )

//console.log( "index : " + index  ) 

if( index > -1 ) { // 如果找到了 ?  就进入内部

var s = source.substring( 0 , index )  // 从 source 中截取 index 之前的内容 ( index 以及 index 之后的内容都被舍弃 )

//console.log( "s : " + s  ) 

var date = new Date() // 创建一个 Date 对象的 一个 实例

var time = date.getTime()  // 从 新创建的 Date 对象的实例中获得该时间对应毫秒值

e.src = s + "?time=" + time  // 将 加了 尾巴 的 地址 重新放入到 src 上

//console.log( e.src ) 

} else {

var date = new Date()

e.src = source + "?time=" + date.getTime()

}

}

如回答不详细可追问

CSS是Cascading Style Sheet 的缩写。译作「层叠样式表单」。是用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

你可能对CSS这个名词比较陌生,实际上无论你用Internet Explorer还是

Netscape Navigator在网上冲浪,几乎随时都在与CSS打交道,在网上没有使用过CSS的网页可能不好找。不管你用什么工

具软件制作网页,都有在有意无意地使用CSS。用好CSS能使你的网页更加简炼,为什么同样内容的网页,有的人做出来有

几十KB,而高手做出来只有十几KB,CSS在其中的作用是不言而喻的。我把我在使用CSS中的一些小经验以及一些网友来信

提问的问题整理出来,供诸位参考。

1、CSS在网页制作中一般有三种方式的用法,那么具体在使用时该采用哪种用法?

当有多个网页要用到的CSS,采用外连CSS文件的方式,这样网页的代码大大减少,修改起来非常方便;只在单个网页

中使用的CSS,采用文档头部方式;只有在一个网页一、两个地方才用到的CSS,采用行内插入方式。

2、CSS的三种用法在一个网页中要以混用吗?

三种用法可以混用,且不会造成混乱。这就是它为什么称之为“层叠样式表”的原因,浏览器在显示网页时是这样处

理的:先检查有没有行内插入式CSS,有就执行了,针对本句的其它CSS就不去管它了;其次检查头部方式的CSS,有就执行

了;在前两者都没有的情况下再检查外连文件方式的CSS。因此可看出,三种CSS的执行优先级是:行内插入式、头部方

式、外连文件方式。

3、在Dreamweaver3中如何使外部文件式CSS?

在Dreamweaver3中使用外连文件式CSS并没有特殊要求,同样是用记事本创建一个*.css文件,在网页的<head>与

</head>之间加上一句这样的代码:<link rel="stylesheet" href="在这里填上你的CSS文件地址(相对路径+文件

名)" type="text/css">就行了。

4、如何用Dreamweaver3快速创建CSS外连式文件?

对于一个初接触CSS的网页设计人员来讲,要用记事之类的编辑器,去创建一个CSS外连式文件是相当困难的。由于

Dreamweaver3对CSS支持的很好,用它来帮助就轻松多了。具体可以这样操作:

1)先在纸上写好在网站的网页中可能要用到的格名称,然后在Dreamweaver3的编辑窗中调出CSS面板,一个一个地定

义,并在一个空白页上适当地写一点相关内容,边定义边试用,效果不满意,立即修改;

2)全部定义好后,再用记事本创建一个空的CSS外连式文件,把在<head>与</head>之间的那段定义好的CSS复制

到CSS文件中去,就大功告成了。整个过程就是点鼠标,方便吧?

5、在Dreamweaver3中采用行内插入式CSS要手动写代码吗?

不用!先用CSS面板定义好要用的CSS,然后,在要插入CSS的标记插入:style="",再把你刚才定义的CSS从<head>

后面拖到这个双引号中来,把花括号以外的部分删去就行了。

6、在方档头部方式和外连文件方式的CSS中都有“<!--”和“-->”,好象没什么用,不要可以吗?

这一对东东的作用是为了不引起低版本浏览器的错误。如果某个执行此页面的浏览器不支持CSS,它将忽略其中的内

容。虽然现在使用不支持CSS浏览器的人已很少了,由于互联网上几乎什么可能都会发生,所以还是留着为妙。

7、如何给一部分文字加背景色?

给文字加上不同颜色,在DW3中只要在属性面板上选取文字的颜色就行了,非常方便,但要给部分文字加不同的背景色

却没有相应的功能,我们可以先做一个定义背景色的CSS(如:bgstyle),在DW3中点几下鼠就完成了。如一个定义淡黄色

背景的CSS是这样的:

<style type="text/css">

<!--

.bgstyle { background: #FFFFCC}

-->

</style>

在要用时选取那段文字,再在CSS面板上点一下“bgstyle”就行了。

8、如何给部分文字加背景图像?

与加背景色操作类似,中是在背景在选择加载图象就是了,一个定义好的加背景图象的CSS例子的代码是这样的:

<style type="text/css">

<!--

.imgbgstyle { background-image: url(/logo.gif)}

-->

</style>

在要用时选取那段文字,再在CSS面板上点一下“imgbgstyle”就行了。

9、如何使页面的背景在文字“滚动”时背景图案静止不动?

要使背景图案不随文字“滚动”的CSS是这样的:

<style type="text/css">

<!--

BODY { background: purple url(/bg.jpg)

background-repeat:repeat-y

background-attachment:fixed

}

-->

</style>

10、如何定义字间距?

在DW3中CSS的属性定义对话框(style Definition for .style1)的“Block”上的“letter spaceing”属性定义的就

是字间距,它指的是每一个字符之间的额外间距,经长度为单位,正负值均可,当取负值时产生字符挤在一起的效果。下

面代码是一个定义好的字间距CSS例子:

<style type="text/css">

<!--

.style1 { letter-spacing: 3px}

-->

</style>

11、如何给文字加上划线、下划线、删除线和闪烁?

在DW3中CSS的属性定义对话框(style Definition for .style1)的“Type”上的“decoration”属性定义的就是这些

内容,要注意的是闪烁属性有些版本的浏览器不支持,少用为好。下面是一个定义好上述效果的CSS例子:

<style type="text/css">

<!--

.style1 { text-decoration: underline overline line-through blink}

-->

</style>

其中: “underline”是定义下划线;“overline ”是定义上划线;“ line-through”定义的是删除线;“blink”

定义的是文字闪烁。

12、如何使网页具有“首行缩进”功能?

由于DW3输入空格不方便,利用“首行缩进”将弥补这个不足。在DW3中CSS的属性定义对话框(style Definition

for .style1)的“Block”上的“text-indent”属性定义的就是“首行缩进”,所谓“首行”是指每段内容的第一行,也

就是直接按回车键就形成了一个新的段落。缩进最好以“em”(字符)为单位,比如:汉字编排要求每段开始缩进两个汉

字,设置好的CSS如下所示:

<style type="text/css">

<!--

.style1 { text-indent: 2em}

-->

</style>

在DW3要注意:在DW3中CSS的属性定义对话框(style Definition for .style1)的“Block”上的“text-indent”右

面的缩进单位选择框中“ems”指的就是“em”。

13、在用表格进行排版时,能使某一方向上的内容离开表格线一点吗?

可以!在DW3中CSS的属性定义对话框(style Definition for .style1)的“Box”上的“margin”定义的就是内容离

开边缘的距离,分别可定义四个方向:“top”“bottom”“left”“right”。下面就是定义在左边离开“10px”的CSS例

子代码:

<style type="text/css">

<!--

.style1 { margin: 0px 0px 0px 10px}

-->

</style>

14、能给某部分内容加边框吗?

用CSS可以给某部分内容加边框,在DW3中CSS的属性定义对话框(style Definition for .style1)的“Border”定义

的就是边框线,“top”“bottom”“left”“right”四边可分别定义线的粗细和颜色,这些定义好后不要忘记在下面的

“style”中定义线型,否则将看不边框线,因为默认的线型是“none”。下面是一个定义了上边框为:蓝色细线;左边框

为:绿色中粗线的CSS例子:

<style type="text/css">

<!--

.style1 { border: solidborder-width: thin 0px 0px mediumborder-color: #0000FF black black #00FF00}

-->

呵呵,这个程序没有问题

imagettftext($im,20,0,3,25,$font,"comic.ttf",$str)

这里需要一个comic.ttf字体文件,必须放在那个php程序同目录下

你是不是没有这个字体文件

如果没有,可以到系统的C:\Windows\Fonts目录下拷贝一个(拷个几百KB大小的就足够用了)

我试了你的程序,生成的图片效果不是很好,我以前写了一个,给你参考下把,虽然也是修改的网上的:

<?

//获取验证码图片模块

session_start()

//记得去掉下面注释

if (!isset($_GET["sid"])||$_GET["sid"]==""||$_GET["sid"]!=session_id())die()

Header("Content-type:image/png")

//定义header,声明图片文件,最好是png,无版权之扰

//生成新的四位整数验证码

//session_id($_GET["sid"])

//开启session

$authnum_session = ''

$str = 'ABCDEFGHIJKMNPQRSTUVWXYZ1234567890'

//定义用来显示在图片上的数字和字母

$l = strlen($str)

//得到字串的长度

//循环随机抽取四位前面定义的字母和数字

for ($i=1$i<=4$i++)

{

$num=rand(0,$l-1)

//每次随机抽取一位数字从第一个字到该字串最大长度,

//减1是因为截取字符是从0开始起算这样34字符任意都有可能排在其中

$authnum_session.= $str[$num]

//将通过数字得来的字符连起来一共是四位

}

$_SESSION["checkCode"]=$authnum_session

//用session来做验证也不错注册session,名称为authnum_session,

//其它页面只要包含了该图片

//即可以通过$_SESSION["checkCode"]来调用

//生成验证码图片,

//srand((double)microtime()*1000000)

mt_srand()

$im = imagecreate(100,40)//图片宽与高

//主要用到黑白灰三种色

$black = ImageColorAllocate($im, mt_rand(0,245),mt_rand(0,200),mt_rand(0,200))

$white = ImageColorAllocate($im, 255,255,255)

$gray = ImageColorAllocate($im, 200,200,200)

//将四位整数验证码绘入图片

imagefill($im,168,30,$gray)

//如不用干扰线,注释就行了

$li = ImageColorAllocate($im, 220,220,220)

for ($i=0$i<0$i++)

{//加入3条干扰线也可以不要视情况而定,因为可能影响用户输入

imageline($im,mt_rand(0,30),mt_rand(0,41),mt_rand(80,90),mt_rand(0,41),$li)

} //字符在图片的位置

//imagestring($im, 5, 8, 2, $authnum_session, $white)

// Set the enviroment variable for GD

putenv('GDFONTPATH=' . realpath('.'))

// Name the font to be used (note the lack of the .ttf extension)

//$font = 'mvboli'

//$font = imageloadfont("mvboli.ttf")

//imagestring($im,$font, 8, 2, $authnum_session, $white)

//imagettftext ( $im,20.0, 0, 0, 30, $white,"FELIXTI.TTF", $authnum_session )

for ($i=0$i<4$i++)

{

imagettftext ( $im,20.0, mt_rand(0,40)-20, $i*25+3, 30, $white,"FELIXTI.TTF", substr($authnum_session,$i,1) )

}

for ($i=0$i<90$i++) //加入干扰象素

{

imagesetpixel($im, mt_rand()%100-2 , mt_rand()%40-2 , $gray)

}

ImagePNG($im)

ImageDestroy($im)

?>

同样这行代码需要一个字体文件,你可以把它改成你拷过来的的字体文件名

imagettftext ( $im,20.0, mt_rand(0,40)-20, $i*25+3, 30, $white,"FELIXTI.TTF", substr($authnum_session,$i,1) )