验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。
当然,以上是学术性解释,我们平常见到的最多的就是以下验证码:
废话不多说,直接上干货,我们先说Java如何生成验证码,下面用一个小例子说明:
1.验证码是用0-9和a-z随机生成4-6位不等的字符串,存到session中,每次点击换一换会更新session,前台输入的验证码会和保存的session比较做判断。
2.具体做法是前端页面有个image,src指向生成验证码的页面,每次点击可以换验证码,form表单的action提交给登录判断的页面。C#和java差别不大,详见源码,代码如下所示:
3.前台代码,碍于篇幅,代码有所缩略,需要完整源码的可以在公众号留言:
<script type="text/javascript">
//验证码的更换
function changeValidateCode() {
document.getElementById("validateCode").src =
"ValidateCodeServlet?rand=" + Math.random();
}
</script>
<input type="text" class="input input-big" name="verifyCode" placeholder="填写右侧的验证码" data-validate="required:请填写右侧的验证码" />
<img src="ValidateCodeServlet" id="validateCode" title="点击换一换" width="100" height="32" class="passcode" style="height:43px;cursor:pointer;"
onclick="changeValidateCode()">
4.产生验证码的Servlet:
@WebServlet("/ValidateCodeServlet")
public class ValidateCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public ValidateCodeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应头 Content-type类型
response.setContentType("image/jpeg");
// 获取二进制数据输出流对象
ServletOutputStream out = response.getOutputStream();
// 创建缓冲图象
int width = 100;
int height = 32;
BufferedImage imgbuf = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = imgbuf.createGraphics();
// 设定背景色
g.setColor(getRandColor(200, 250));
// 设定图像形状及宽高
g.fillRect(0, 0, width, height);
// 随机产生100条干扰线,使图象中的认证码不易被其它程序探测到
Random r = new Random();
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 100; i++) {
int x = r.nextInt(width);
int y = r.nextInt(height);
int xl = r.nextInt(12);
int yl = r.nextInt(12);
g.drawLine(x, y, x + xl, y + yl);
}
// 随机产生100个干扰点,使图像中的验证码不易被其他分析程序探测到
g.setColor(getRandColor(120, 240));
for (int i = 0; i < 100; i++) {
int x = r.nextInt(width);
int y = r.nextInt(height);
g.drawOval(x, y, 0, 0);
}
// 随机产生0-9之间的4位数字验证码
g.setFont(new Font("Times New Roman", Font.PLAIN, 35));
String code = "";
for (int i = 0; i < 4; i++) {
String rand = String.valueOf(r.nextInt(10));
code += rand;
g.setColor(new Color(20 + r.nextInt(110), 20 + r.nextInt(110), 20 + r.nextInt(110)));
g.drawString(rand, 20 * i + 10, 28);
}
//System.out.println("生成的随机数是:" + code);
// 将验证码保存到session中
request.getSession().setAttribute("SESSION_VALIDATECODE", code);
// 输出图像
ImageIO.write(imgbuf, "JPEG", out);
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
// 获取指定范围的随机颜色
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 255;
if (fc < 0)
fc = 0;
if (bc > 255)
bc = 255;
if (bc < 0)
bc = 0;
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);
}
}
5.后台用于判断验证码的Servlet:
@WebServlet("/ApplicantLoginServlet")
public class ApplicantLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response){
// 获取请求参数
String verifyCode = request.getParameter("verifyCode");
// 判断验证码是否正确
String sessionValidateCode = (String) request.getSession().getAttribute("SESSION_VALIDATECODE");
if (!sessionValidateCode.equals(verifyCode)) {
out.print("alert('请正确输入验证码!');");
}else {// 错误提示login.html
out.print("alert('用户名或密码错误,请重新输入!');");
}
其他还有诸如文字验证码:
原理其实是一样的,随机生成字符串,存入session,后台判断即可.
还有数字运算的验证码,原理一样的: