网页登录时验证码功能的实现

  • 在我们日常上网时,经常会遇到要登录的界面,我们会发现他会让你输入账号,密码外,还需要输入随机生成的验证码。

  • 作用: 不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

  • 效果如下图所示:

  • 点击图片或刷新页面,都可以刷新验证码图片。下面就为大家讲解这个功是如何实现的。

  • 在这里说明一下,针对这个功能的实现,我是在后端使用Java语言生成图像的方式来实现。我对其实现的代码进行了封装,将其做成一个工具类。以便再其他场景的使用,和代码移植的便捷性。

  • 以下就是该工具类:

  • ImageUtils类

package com.wdhcr.tools;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;/** 实现获取验证码图像功能的工具类* 返回一个BufferedImage对象** */
public class ImageUtils {// 随机字符集合中去除掉了0和o,O,1和l,因为这些不易区分private static String CHECK_CODES = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";//  该方法主要作用是生成随机的颜色private static Color getRandColor(int s, int e) {Random random = new Random();if (s > 255)s = 255;if (e > 255)e = 255;int r, g, b;r = s + random.nextInt(e - s); // 随机生成RGB颜色中的r值g = s + random.nextInt(e - s); // 随机生成RGB颜色中的g值b = s + random.nextInt(e - s); // 随机生成RGB颜色中的b值return new Color(r, g, b);}/*@param:width , height 指定生成验证码的宽度和高度HttpServletRequest request 传入需要获取验证码图片的会话请求,将验证码四位验证码放入到session域中@return:BufferedImage image对象*/public static BufferedImage getPicture(int width, int height, HttpServletRequest request) {// 创建BufferedImage对象,其作用相当于一图片BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.getGraphics(); // 创建Graphics对象,其作用相当于画笔Graphics2D g2d = (Graphics2D) g; // 创建Grapchics2D对象Random random = new Random();Font mfont = new Font("幼圆", Font.BOLD, 25); // 定义字体样式,显示大小g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height); // 绘制背景图片大小g.setFont(mfont); // 设置字体g.setColor(getRandColor(180, 200));// 绘制50条颜色和位置全部为随机产生的线条,该线条为2ffor (int i = 0; i < 50; i++) {int x = random.nextInt(width - 1);int y = random.nextInt(height - 1);int x1 = random.nextInt(6) + 1;int y1 = random.nextInt(12) + 1;BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL); // 定制线条样式Line2D line = new Line2D.Double(x, y, x + x1, y + y1);g2d.setStroke(bs);g2d.draw(line); // 绘制直线}//用来保存验证码字符串文本内容StringBuilder sb = new StringBuilder();for (int i = 0; i < 4; ++i) {// 随机生成4个字符/*random.nextInt(CHECK_CODES.length())使用这个方法获取到一个从0到CHECK_CODES.length()*包含0,不包含    CHECK_CODES.length()的一个随机数*使用charAt根据下标的方式取出字符。*/char charAt = CHECK_CODES.charAt(random.nextInt(CHECK_CODES.length()));String sTemp = String.valueOf(charAt);sb.append(sTemp);Color color = new Color(20 + random.nextInt(110), 20 + random.nextInt(110), random.nextInt(110));g.setColor(color);// 将生成的随机数进行随机缩放并旋转制定角度 PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示/* 将文字旋转制定角度 */Graphics2D g2d_word = (Graphics2D) g;AffineTransform trans = new AffineTransform();trans.rotate((45) * 3.14 / 180, 15 * i + 8, 7);/* 缩放文字 */float scaleSize = random.nextFloat() + 0.8f;if (scaleSize > 1f)scaleSize = 1f;trans.scale(scaleSize, scaleSize);g2d_word.setTransform(trans);g.drawString(sTemp, 15 * i + 18, 14);}/** 将生成的四位随机验证码,放入session域中,方便登录controller的获取,验证。*当有controller调用获取验证码工具类时,需要传入本次请求的会话request,并获取session域。将验证码数据放入其中。* */HttpSession session = request.getSession(true);session.setAttribute("randCheckCode", sb.toString());System.out.println("sRand=" + sb.toString());g.dispose(); // 释放g所占用的系统资源//返回画布return image;}}
  • controller层类,接收到前端请求
package com.wdhcr.controller;import com.wdhcr.tools.ImageUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;@Controller
public class CheckController {/** 当页面请求时,使用画布获取一个验证码图像* 返回到页面* 接收前端获取验证码的请求,使用画布随机生成一个四位数的验证码图像* 将生成的四位数字,数字或字母放在一个session域中使得登录验证的controller中可以获取到该值,判断登陆验证* 使用mageIO.write(image, "JPEG", response.getOutputStream());输出图片* 使其再前端可以接收再图片显示出来* */@RequestMapping(value = "/checkCode")public void checkCode(HttpServletRequest request, HttpServletResponse response) throws IOException {//设置编码格式request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");// 设置不缓存图片response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "No-cache");response.setDateHeader("Expires", 0);// 指定生成的响应图片,一定不能缺少这句话,否则错误.response.setContentType("image/jpeg");/** @param* 传入生成图像长度和宽度,还有本次会话的请求HttpServletRequest对象request* @return* 返回一个BufferedImage对象* */BufferedImage image = ImageUtils.getPicture(80, 35, request);// 将图像输出到response输出流中。//response.getOutputStream()获取response输出流ImageIO.write(image, "JPEG", response.getOutputStream()); // 输出图片}
}
  • 前端html或jsp页面代码
<div class="control-group"><label class="control-label visible-ie8 visible-ie9">验证码</label><div class="controls"><div class="input-icon left"><i class="icon-book"></i><%--                    这里是输入验证码图片中的字符,传入后台进行验证--%><input style="width:49%;float:left;height: 24px;" type="text" placeholder="验证码" name="check"id="check"/><span style="cursor:pointer;float: right;height: 34px; width: 30%;">
<%--                        这里需要注意src的路径,为controller层指定的路径@RequestMapping(value = "/checkCode")的路径--%>
<%--                        Reload()方法实现点击一次请求一次后台controller--%><img id="CreateCheckCode" style="width: 100%;height:100%;" src="checkCode.do" onclick="Reload()" /></span></div></div></div>
  • 这里的前端代码主要实现功能的是

      <%-- 这里是输入验证码图片中的字符,传入后台进行验证--%><input style="width:49%;float:left;height: 24px;" type="text" placeholder="验证码" name="check"id="check"/><span style="cursor:pointer;float: right;height: 34px; width: 30%;"><%-- 这里需要注意src的路径,为controller层指定的路径@RequestMapping(value =  "/checkCode")的路径--%><%--Reload()方法实现点击一次请求一次后台controller--%><img id="CreateCheckCode" style="width: 100%;height:100%;" src="checkCode.do"onclick="Reload()"/>
    
  • 实现点击换验证码图片的js代码

    <!-- 验证码图片点击切换 --><!-- 通过Date来改变每次访问的url不同 -->
<script>function Reload() {document.getElementById("CreateCheckCode").src =// 获取当前时间使其请求不重复document.getElementById("CreateCheckCode").src + "?nocache=" + new Date().getTime() + ".do";}</script>
  • 在工具类中我将四位字符放到了本次会话的session域中,所以在登录的controller验证时加入如下代码:
//创建session域的对象,获取域中的数据if (session.getAttribute("randCheckCode").toString().equalsIgnoreCase(check)) {try {//验证成功后,转发到index页面request.getRequestDispatcher("index.jsp").forward(request, response);} catch (ServletException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}else {//验证码输入错误,弹窗提示,并返回到login页面writer.println("<script>alert('登录失败了!验证码错误!!!');</script>");}
  • 以上就是登录时验证码功能实现的步骤以及源码。

网页登录时验证码功能的实现相关推荐

  1. .NET Core实战项目之CMS 第十六章 用户登录及验证码功能实现

    前面为了方便我们只是简单实现了基本业务功能的增删改查,但是登录功能还没有实现,而登录又是系统所必须的,得益于 ASP.NET Core的可扩展性因此我们很容易实现我们的登录功能.今天我将带着大家一起来 ...

  2. vue.js项目实战运用篇之抖音视频APP-第十一节: 注册登录及验证码功能

    [温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...

  3. 关于登录时验证码无法显示

    关于登录时验证码无法显示 我当时的情况时redis密码不对,导致无法显示

  4. 【登录时验证码一直错误】阿里云SLB负载均衡,如何session共享

    场景: 小程序休眠期是在 公司机房放着呢,现在要使用,使用期上阿里云. 在6上使用阿里云的SLB做负载均衡.将请求分发给124和192. 操作步骤: 1.先在124和192上搭好后端环境 测试好 后台 ...

  5. 网页登录时密码如何传输?

    今天突发奇想想看下一般网站登录时密码是如何传输的. 首先是QQMail,gmail,各大网上银行等对于我非常重要的登录网站:      https      https的安全性自然是很高. 其次是通常 ...

  6. python判断网页密码加密方式_python实现网页登录时的rsa加密流程

    对某些网站的登录包进行抓包时发现,客户端对用户名进行了加密,然后传给服务器进行校验. 使用chrome调试功能断点调试,发现网站用javascript对用户名做了rsa加密. 为了实现网站的自动登录, ...

  7. python实现网页登录时的rsa加密流程

    对某些网站的登录包进行抓包时发现,客户端对用户名进行了加密,然后传给服务器进行校验. 使用chrome调试功能断点调试,发现网站用javascript对用户名做了rsa加密. 为了实现网站的自动登录, ...

  8. 【python】简单使用selenium编写无界面谷歌浏览器的网页登录和签到功能

    使用python编写简单的关于服务器端网页自动登录及签到的功能 注:仅用于测试人员自动化脚本测试,请勿用于其他用途 ------------------------------------------ ...

  9. ASP.NET登录时验证码的制作与验证

    ASP.NET 验证码的制作与校验(使用 cookie 传值) (1)验证码应该是图片格式,不能是文字格式,即无法用鼠标选中.(2)验证码上应该有噪点和干扰线条.(3)验证码应该回避相似字符,如&qu ...

最新文章

  1. 「SAP技术」SAP MM 委外加工采购流程里副产品的收货
  2. HDU1899 Sum the K-th's(树状数组)
  3. Juce源代码分析(一)Juce的优势
  4. node.js 学习笔记三:路由url
  5. 2017年9月2日普级组T2 跳格子
  6. 【NLP】jieba分词-Python中文分词领域的佼佼者
  7. 关于SQL SERVER高并发解决方案
  8. jdk8 接口默认方法_JDK 8中方便的新地图默认方法
  9. Oracle数据库(二)—— 基本的SQL SELECT语句
  10. laravel的重定向
  11. Boolan STL 第三周笔记
  12. spark的rdd的含义_Spark里边:到底是什么RDD
  13. solarwinds ipam功能说明手册
  14. java ee ssh三大框架知识点_详解JAVAEE——SSH三大框架整合(spring+struts2+hibernate)...
  15. 音视频实时交互/语音通话/即时通话/连麦,EasyRTC即时通讯系统全方位服务
  16. CNC加工老师傅的经验分享 这些你都知道吗?
  17. oracle查询所有去掉重复的数据库,ORACLE数据库查询删除重复记录的三种方法
  18. “用户请求取消当前的操作”的几种解决办法
  19. 斐讯音箱控制扫地机器人_【斐讯 R1 智能音箱使用体验】操作|功能|音质|识别_摘要频道_什么值得买...
  20. c语言中ifelse意义,c语言if和else if的区别

热门文章

  1. javascript属性
  2. sarama-cluster消费者运行时报panic: non-positive interval for NewTicker
  3. 美国与印度的职场文化有何差异?Ravi Krishnamurthy博士专访
  4. 基于SSH开发网上机票销售系统
  5. 关于欧几里得定理和拓展欧几里得定理的理解 续
  6. tinyxml/tinyxml2遍历所有节点
  7. Linux内存管理(三):内存与内存分布
  8. 三个向量叉乘的公式的证明推导
  9. 【架构】软件代码的耦合性和内聚性,以几个简单小例子说明
  10. 三个白帽 - pwnme_k0