怎样用java实现验证码

Python022

怎样用java实现验证码,第1张

现在许多系统的注册 登录或者发布信息模块都添加的随机验证码功能 就是为了避免自动注册程序或者自动发布程序的使用

验证码实际上就是随机选择一些字符以图片的形式展现在页面上 如果进行提交操作的同时需要将图片上的字符同时提交 如果提交的字符与服务器session保存的不同 则认为提交信息无效 为了避免自动程序分析解析图片 通常会在图片上随机生成一些干扰线或者将字符进行扭曲 增加自动识别验证码的难度

在这里 我们使用java实现验证码

<%@ page contentType= image/jpeg import= java awt * java awt image * java util * javax imageio * %>

<%!

Color getRandColor(int fc int bc){//给定范围获得随机颜色

Random random = new Random()

if(fc>) fc=

if(bc>) bc=

int r=fc+random nextInt(bc fc)

int g=fc+random nextInt(bc fc)

int b=fc+random nextInt(bc fc)

return new Color(r g b)

}

%>

<%

//设置页面不缓存

response setHeader( Pragma No cache )

response setHeader( Cache Control no cache )

response setDateHeader( Expires )

// 在内存中创建图象

int width= height=

BufferedImage image = new BufferedImage(width height BufferedImage TYPE_INT_RGB)

// 获取图形上下文

Graphics g = image getGraphics()

//生成随机类

Random random = new Random()

// 设定背景色

g setColor(getRandColor( ))

g fillRect( width height)

//设定字体

g setFont(new Font( Times New Roman Font PLAIN ))

// 随机产生 条干扰线 使图象中的认证码不易被其它程序探测到

g setColor(getRandColor( ))

for (int i= i<i++)

{

int x = random nextInt(width)

int y = random nextInt(height)

int xl = random nextInt( )

int yl = random nextInt( )

g drawLine(x y x+xl y+yl)

}

// 取随机产生的认证码( 位数字)

String codeList = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

String sRand=

for (int i= i<i++){

int a=random nextInt(codeList length() )

String rand=codeList substring(a a+ )

sRand+=rand

// 将认证码显示到图象中

g setColor(new Color( +random nextInt( ) +random nextInt( ) +random nextInt( )))//调用函数出来的颜色相同 可能是因为种子太接近 所以只能直接生成

g drawString(rand *i+ )

}

// 将认证码存入SESSION

session setAttribute( rand sRand)

// 图象生效

g dispose()

// 输出图象到页面

ImageIO write(image JPEG response getOutputStream())

out clear()

out = pageContext pushBody()

lishixinzhi/Article/program/Java/hx/201311/25536

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

}

}

如回答不详细可追问

原理:

1.随机生成4个数字 用到了Random类

2.对这4个数字设置字体格式 用 setFont方法

3.改变字体颜色用setColor 然后随机生成颜色

代码如下

package s1

import java.awt.Color

import java.awt.Font

import java.awt.Graphics

import java.awt.image.BufferedImage

import java.io.IOException

import java.io.PrintWriter

import java.util.Random

import javax.imageio.ImageIO

import javax.jms.Session

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 GetImage 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 {

// 发送图片不能够添加这2行代码

// response.setContentType("text/htmlcharset=UTF-8")

//request.setCharacterEncoding("UTF-8")

int width=100

int height=50

//获得一张图片

BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)

Graphics g=image.getGraphics()

g.setColor(Color.WHITE)

g.fillRect(1, 1, width-2, height-2)

g.setFont(new Font("宋体",Font.BOLD,30))

Random random=new Random()

//填充的字符串

String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

//缓存生成的验证码

StringBuffer stringbuffer=new StringBuffer()

//随机生成验证码的颜色和字符

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

{ //设置随机颜色

g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)))

int index=random.nextInt(62)//这里的62就是从填充字符段中随意选取一个位置

String str1=str.substring(index,index+1)

g.drawString(str1, 20*i, 30)//x,y数值设置太小会显示不出来

stringbuffer.append(str1)

}

//将生成的验证码存到服务器

request.getSession().setAttribute("checkcode", stringbuffer.toString())//key和value

//将图片发送给浏览器

ImageIO.write(image, "jpg", response.getOutputStream())

}

}

用户登录界面代码

package s1

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

import javax.servlet.http.HttpSession

public class Login extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/htmlcharset=UTF-8")// 设置服务器发送给浏览器的编码方式

request.setCharacterEncoding("UTF-8")// 客户端向服务器提交的数据的解码方式

// 获得用户提交的数据

String checkcode = request.getParameter("checkcode")

System.out.println(checkcode)

// 判断输入的验证码是不是符合

HttpSession session = request.getSession()// session是存放数据的地方

String str = (String) session.getAttribute("checkcode")

if (str != null) {

if (checkcode.compareToIgnoreCase(str) == 0) // 验证码忽略大小写

response.getWriter().println("验证码输入正确")

else

response.getWriter().println("验证码输入错误")

}

else response.getWriter().println("验证码失效")

// 使用完的验证码信息要删除,返回原页面再输一次,验证码就失效了

session.removeAttribute("checkcode")

}

}