我们总是在登录微信,QQ或者其他一些网页的时候,都会出现一个验证码框,他们有的是数字的,有的是文字的,有的是混合的,各种各样的。
很好奇是怎么实现的。带着这样的疑问。
目录
然后在之前创建的随机数方法里,进行循环答应,输出4个随机数
接下来我们需要定义图片的宽度和高度
BufferedImage对象是图片的缓冲流,用于GRB绘制对象,在内存操作过程中,将内存操作的每一个步骤绘制到内存里面存储起来。将缓冲流进行输出。产生一张图片。
//2.定义图片的高度和宽度
int width =120;
int height =25;
//建立bufferedImage对象,制定图片的长度和宽度以及色彩
BufferedImage bi =new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
//3.获取Graphics2D 绘制对象,开始绘制验证码
Graphics2D g =bi.createGraphics();
//4.设置文字的子图验证和大小
Font font =new Font("微软雅黑", Font.PLAIN, 20);
//5.设置字体的颜色
Color color =new Color(0,0,0);
//将颜色和字体放入
g.setFont(font);
g.setColor(color);
g.setBackground(new Color(226,226,226));//背景颜色
//开始绘制对象
g.clearRect(0, 0, width, height);
//绘制形状,获取距形对象
FontRenderContext context =g.getFontRenderContext();//文字读取上下文
Rectangle2D bounds =font.getStringBounds(code, context);//将生成的验证码放入
//计算文字的坐标和间距
double x =(width -bounds.getWidth())/2;
double y =(height -bounds.getHeight())/2;
double ascent =bounds.getY();
double baseY =y -ascent;
g.drawString(code, (int)x, (int)y);
//结束配置
g.dispose();
//将图片保存到制定地方,输出
try {
ImageIO.write(bi,"jpg",response.getOutputStream());
//刷新响应流
response.flushBuffer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return code;//用于验证码的对比和存储
做完这些后,我们需要定义一个code.jsp页面
<%@ page import="com.kilig.code.CaptcahCode" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
//1:清空浏览器缓存,目的是为了清空浏览器的缓存,因为浏览器
//会对网站的资源文件和图像进行记忆存储,如果被浏览器加载过的图片就记忆起来,记忆以后
//文件就不会和服务器在交互,如果我们验证不清空的话可能会造成一个问题就是:验证刷新以后没有效果。
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//2:调用编写的生成验证码的工具
String code = CaptcahCode.drawImage(response);
session.setAttribute("code",code);
//3:如何解决getOutputStream异常问题
out.clear();
out = pageContext.pushBody();
%>
然后在编制输出页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Java Verification Code</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<img src="code.jsp" alt="" id="code">
<a href="javascript:void();" onclick="changeCode()">看不清,点我</a>
<script>
function changeCode(){
document.getElementById("code").src ="code.jsp?d="+new Date().getTime();
}
</script>
</body>
</html>
运行看效果:(每次刷新都不一样)
2.算数表达式验证码
通过观察算数表达式的验证码图片我们得出:
public static String drawImageVerificate(HttpServletResponse response) throws IOException {
//定义验证码的宽度和高度
int width =100, height =30;
//在内存中创建图片
BufferedImage image =new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
//创建图片的上下文
Graphics2D g =image.createGraphics();
//创建随机对象,此随机对象主要用于算数表达式的数字
Random random =new Random();
//设置背景
g.setColor(getRandomColor(240,250));
//设置字体
g.setFont(new Font("微软雅黑", Font.PLAIN,22));
//开始绘制
g.fillRect(0,0,width,height);
//干扰线的绘制 ,绘制线条到图片中
g.setColor(getRandomColor(180,230));
for (int i = 0; i <100 ; i++) {
int x =random.nextInt(width);
int y =random.nextInt(height);
int x1 =random.nextInt(60);
int y1 =random.nextInt(60);
g.drawLine(x, y,x1,y1);
}
//开始对算数验证码表达式进行拼接
int num1 =(int)(Math.random()*10+1);
int num2 =(int)(Math.random()*10+1);
int symbel =random.nextInt(3); //定义符号,产生一个[0,2]之间的随机整数
//记录符号
String symbelstr=null;
int result =0;
switch (symbel){
case 0 : symbelstr ="+";result =num1+num2; break;
case 1 : symbelstr ="-";result =num1-num2; break;
case 2 : symbelstr ="*";result =num1*num2; break;
}
//计算表达式
String calc =num1 + " "+ symbelstr +" "+ num2 +"=?";
//设置随机颜色
g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
//绘制表达式
g.drawString(calc, 5, 25);
//结束绘制
g.dispose();
try{
//输出图片到页面
ImageIO.write(image,"JPEG",response.getOutputStream());
return String.valueOf(result);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
//return null;
}
3.使用框架进行实现验证码
kcaptcha实现技术 💁💁💁点击打开kaptcha的官网 网站需要VPN哦,需要VPN的可以私聊我。
Kaptcha是一个基于SimpleCaptcha的验证码开源项目。
1.在官网上下载Kaptcha的相关jar包。并且倒入到lib文件夹中
2.首先配置web.xml
3.然后创建一个页面的jsp index.jsp
启动服务
那么字母的定义,图片的宽度高度,干扰线的设置怎么去配置呢?
下面,从新引入到web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>Kaptcha</display-name>
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>200</param-value>
</init-param>
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<init-param>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.NoNoise</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
</web-app>
然后运行,进行参数的修改
具体其他参数的配置修改,我从官网上down下来
- Constant 描述 默认值
- kaptcha.border 图片边框,合法值:yes , no yes
- kaptcha.border.color 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue. black
- kaptcha.border.thickness 边框厚度,合法值:>0 1
- kaptcha.image.width 图片宽 200
- kaptcha.image.height 图片高 50
- kaptcha.producer.impl 图片实现类 com.google.code.kaptcha.impl.DefaultKaptcha
- kaptcha.textproducer.impl 文本实现类 com.google.code.kaptcha.text.impl.DefaultTextCreator
- kaptcha.textproducer.char.string 文本集合,验证码值从此集合中获取 abcde2345678gfynmnpwx
- kaptcha.textproducer.char.length 验证码长度 5
- kaptcha.textproducer.font.names 字体 Arial, Courier
- kaptcha.textproducer.font.size 字体大小 40px
- kaptcha.textproducer.font.color 字体颜色,合法值: r,g,b 或者 white,black,blue. black
- kaptcha.textproducer.char.space 文字间隔 2
- kaptcha.noise.impl 干扰实现类 com.google.code.kaptcha.impl.DefaultNoise
- kaptcha.noise.color 干扰颜色,合法值: r,g,b 或者 white,black,blue. black
- kaptcha.obscurificator.impl 图片样式:
- 水纹com.google.code.kaptcha.impl.WaterRipple
- 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy
- 阴影com.google.code.kaptcha.impl.ShadowGimpy
- com.google.code.kaptcha.impl.WaterRipple
- kaptcha.background.impl 背景实现类 com.google.code.kaptcha.impl.DefaultBackground
- kaptcha.background.clear.from 背景颜色渐变,开始颜色 light grey
- kaptcha.background.clear.to 背景颜色渐变,结束颜色 white
- kaptcha.word.impl 文字渲染器
- com.google.code.kaptcha.text.impl.DefaultWordRenderer
- kaptcha.session.key session key KAPTCHA_SESSION_KEY
- kaptcha.session.date session date KAPTCHA_SESSION_DATE
举个例子,比方说加入对文字内容的配置 ,要求只可以是123456789数字
让我们运行看一看,就会产生一个只有4位数字,并且宽度200,高度50的没有干扰线的验证码图片
不同方式的组合配置,会有不同的效果:
4.案例学习:
我们引入第三方的框架:jquery
增加一个时间搓,点击功能,当店家页面,实现刷新
在编写一个javascript的方法,看是否可以获取我们的用户输入的验证码
此时我们的客户端以及做好了,我们去完成我们的服务端的设计
在上面的介绍里,我们认识到,获取验证码框的函数是 kaptcha.session.key session key KAPTCHA_SESSION_KEY
如果用户输入的验证码和产生在服务器端的验证码一致,那么用户输入成功
equalsIgnoreCase(); 方法,不用区分大小写
LoginServlet
package com.kilig.code;
import java.io.IOException;
import java.io.PrintWriter;
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.swing.text.StyleConstants.CharacterConstants;
import com.google.code.kaptcha.Constants;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置编码
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
//需要获取浏览器的输出流对象
PrintWriter out =response.getWriter();
//获取用户传递过来的验证码
String code =request.getParameter("code");
//获取验证码框架产生的验证码
String sessionCode =(String)request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
System.out.println(code+"===="+sessionCode);
if(code != null && sessionCode != null) {
//如果用户输入的验证码和产生在服务器端的验证码一致,那么用户输入成功
if(code.equalsIgnoreCase(sessionCode)) {
System.out.println("Success");
}else {
System.out.println("Fail");
}
}else {
System.out.println("Fail");
}
//刷新和关闭
out.flush();
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>#code{height:25px;}</style>
</head>
<body>
<form action="submit.action">
<p>验证码:<input type="text",name="kaptcha", id="code" maxlength="4" placeholder="请输入验证码">
<img src="kaptcha.jpg" id ="changeCode"/></p>
<p><input type="button" value="登录" id="login"></p>
<div id="result"></div>
</form>
<script src="js/jquery-1.12.4.min.js"></script>
<script>
$(function(){
$("#changeCode").on("click",function(){
$(this).attr("src","kaptcha.jpg?d="+new Date().getTime());
})
//给登录按钮绑定登录事件
$("#login").on("click",function(){
//获取用户输入的验证码
var code =$("#code").val();
var params ={"code":code};
$.post("login",params,function(data){
if(data =="Success"){
$("#result").html("验证码输入正确!!");
}else{
$("#result").html("验证码输入有误,请重新输入。。。");
$("#code").val("").focus();
}
});
});
});
</script>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>Web</display-name>
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>200</param-value>
</init-param>
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<init-param>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.NoNoise</param-value>
</init-param>
<!-- "kcode"生成好的验证码 -->
<!--
<init-param>
<param-name>kaptcha.session.key </param-name>
<param-value>kcode</param-value>
</init-param>
-->
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
<!-- 注册LoginServlet -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.kilig.code.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>