专栏首页浩Coding每日一码(1)--验证码的生成和使用

每日一码(1)--验证码的生成和使用

验证码(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,后台判断即可.

还有数字运算的验证码,原理一样的:

本文分享自微信公众号 - 浩Coding(gh_c4a2e63d2ca7),作者:浩

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【程序猿硬核科普】为什么固态硬盘删除数据后无法恢复 | 附常用的硬盘数据恢复软件

    本篇文章主要讲机械硬盘删除文件的原理以及SSD固态硬盘删除数据后为何无法恢复,文末附常用的硬盘数据恢复软件。

    浩Coding
  • Java EE之SSM框架整合开发 -- (7) MyBatis映射器

    2.在MyBatis中针对不同的数据库软件,<insert>元素如何将主键回填?

    浩Coding
  • 【程序猿硬核科普】Linux下Shell编程杂记

    date 命令的另一个扩展是 -d 选项,可以快速地查明一个特定的日期。相对于当前日期若干天的究竟是哪一天,从现在开始的若干天或若干星期以后,或者以前(过去)。...

    浩Coding
  • LeetCode 41 First Missing Positive

    ShenduCC
  • 字母排序问题(c++实现)

    描述:编写一个程序,当输入不超过60个字符组成的英文文字时,计算机将这个句子中的字母按英文字典字母顺序重新排列,排列后的单词的长度要与原始句子中的长度 相同。例...

    用户2038589
  • 弱校联盟10.3

    n对括号最多需要1+2+..+n次交换,当它是)))..(((的形式时,)))(((需要6次,然后把中间两个交换一下,))()((就还需要5次,再交换一次靠近左...

    饶文津
  • 【USACO 3.2】Magic Squares

    4*2个格子分别为 1234 8765 的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格。 现在给出目标状态,...

    饶文津
  • 1436 孪生素数 2

    1436 孪生素数 2 时间限制: 2 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题目描述 Description 如m=...

    attack
  • C/C++用QT写的五子棋源码

    bear_fish
  • 颜色聚合向量

    package com.imageretrieval.features; /** * 颜色聚合向量<br> * 参考链接:http://www.docin...

    Venyo

扫码关注云+社区

领取腾讯云代金券