登录验证码的实现
程序员文章站
2022-05-19 20:56:48
...
前言:
验证码,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意**密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力**方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答验证码的问题,所以回答出问题的用户就可以被认为是人类。
功能实现:
后端部分:
1.验证码生成的servlet
package control;
import javax.imageio.ImageIO;
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;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
/**
* Created by lc on 2018/8/2.
*/
@WebServlet(name = "Verificationcode",urlPatterns = "/Verificationcode")
public class Verificationcode extends HttpServlet {
// 图形验证码的字符集,系统将随机从这个字符串中选择一些字符作为验证码
private static String codeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 获得验证码集合的长度
int charsLength = codeChars.length();
// 下面3条记录是关闭客户端浏览器的缓冲区
// 这3条语句都可以关闭浏览器的缓冲区,但是由于浏览器的版本不同,对这3条语句的支持也不同
// 因此,为了保险起见,同时使用这3条语句来关闭浏览器的缓冲区
response.setHeader("ragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 设置图形验证码的长和宽
int width = 90, height = 30;
/* Image的一个子类java.awt.image.BufferedImage是带数据缓冲区的图像类,BufferedImage生成的图片
在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便的操作这个图片,通常用来做图片修改
操作如大小变换、图片变灰、设置图片透明或不透明等*/
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
//创建Graphics对象对image进行绘制
Graphics g = image.getGraphics();
Random random = new Random();
//随机设置画笔颜色
g.setColor(getRandomColor(180, 250));
//绘制一个矩形来做验证码背景颜色
g.fillRect(0, 0, width, height);
// 创建字符串变量,用来保存最后随机生成的验证码
StringBuffer validationCode = new StringBuffer();
// 验证码的随机字体
String[] fontNames = { "Times New Roman", "Book antiqua", "Arial" };
// 随机生成4个验证码
for (int i = 0; i < 4; i++) {
// 随机设置当前验证码的字符的字体
g.setFont(new Font(fontNames[random.nextInt(3)], Font.ITALIC,
height));
// 随机获得当前验证码的字符
char codeChar = codeChars.charAt(random.nextInt(charsLength));
validationCode.append(codeChar);
// 随机设置当前验证码字符的颜色
g.setColor(getRandomColor(10, 100));
// 在图形上输出验证码字符,x和y都是随机生成的
g.drawString(String.valueOf(codeChar), 18 * i + random.nextInt(5), height-6+random.nextInt(6));
}
// 获得HttpSession对象
HttpSession session = request.getSession();
// 设置session对象5分钟失效
session.setMaxInactiveInterval(5 * 60);
// 将验证码保存在session对象中,key为validation_code
session.setAttribute("validation_code", validationCode.toString());
//关闭Graphics对象
g.dispose();
OutputStream outS = response.getOutputStream();
ImageIO.write(image, "JPEG", outS);
}
private Color getRandomColor(int minColor, int maxColor) {
Random random = new Random();
if(minColor > 255){
minColor = 255;
}
if(maxColor > 255){
maxColor = 255;
}
//获得r的随机颜色值
int red = minColor+random.nextInt(maxColor-minColor);
int green = minColor + random.nextInt(maxColor-minColor);
int blue = minColor + random.nextInt(maxColor-minColor);
return new Color(red,green,blue);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.登录处理的servlet
package control;
import dao.Userdao;
import entry.User;
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;
import java.io.IOException;
/**
* Created by lc on 2018/6/22.
*/
@WebServlet(name = "LoginPro",urlPatterns = "/LoginPro")
public class LoginPro extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String vcode = request.getParameter("vcode");
HttpSession session = request.getSession();
String validation_code = (String) session.getAttribute("validation_code");
if (vcode.toLowerCase().equals(validation_code.toLowerCase())) {
User user = new User(username, password);
Userdao userdao = new Userdao();
boolean vfpassword = userdao.Vfpassword(user);
if (vfpassword) {
response.getWriter().write("true");
session.setMaxInactiveInterval(3600);
session.setAttribute("username", username);
} else {
response.getWriter().write("false");
}
}else{
response.getWriter().write("false1");
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
前端部分:
登录页面:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>登录</title>
<link rel="stylesheet" href="css/login.css">
<script src="js/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
//登录事件
$("#btn").click(function(){
var username=$("#u").val()
var password=$("#p").val()
var vcode=$("#vcode").val()
$.ajax({
url:"/LoginPro",
data:{
username:username,
password:password,
vcode:vcode
},
success:function(str){
if(str=="true"){
alert("登录成功!");
window.location.href="/Index";
}
else if(str=="false"){
$("#error-show").text("用户名或密码错误!")
}
else{
$("#error-show").text("验证码错误!")
}
}
})
})
//键盘按键事件
$("#p").keydown(function(e){
var curkey= e.which;
if(curkey==13){
$("#btn").click();
return false;
}
}
)
$("#vcode").keydown(function(e){
var curkey= e.which;
if(curkey==13){
$("#btn").click();
return false;
}
}
)
//获得焦点事件
$("#u").focus(
function(){
if($("#error-show").text()!="验证码错误!")
$("#error-show").text("");
})
$("#p").focus(
function(){
if($("#error-show").text()!="验证码错误!")
$("#error-show").text("");
}
)
//更换验证码事件
$("#changevcode").click(
function(){
//通过改变验证码图片的src属性,来更换验证码
//为了防止浏览器直接从缓存读取,每次验证码请求加上一个随机数
$("#vcode_img").attr("src","Verificationcode?num="+Math.random());
if($("#error-show").text()=="验证码错误!"){
$("#error-show").text("");
}
return false;//不触发原来的点击事件
}
)
})
</script>
</head>
<body>
<div class="box">
<h3 class="text-title">登录</h3>
<span class="span-register">还没有帐号?30s<a href="Register.html" class="a-register">注册</a></span>
<div class="clear"></div>
<form method="post">
<p class="text"><input name="username" type="text" id="u" placeholder="用户名/手机号/邮箱" style="height: 30px;width: 280px" />
</p>
<p class="text">
<input name="password" type="password" id="p" placeholder="密码" style="height: 30px;width: 280px"/>
</p>
<div>
<input type="text" name="vcode" placeholder="验证码" style="margin-left: 28px;width: 120px;height: 25px;vertical-align:bottom" id="vcode"/><img src="Verificationcode" alt="" width="90px" height="30px;" id="vcode_img" style="vertical-align:bottom"/><a href="#" style="color: #FF5500;font-size: 12px;text-decoration: none;margin-left: 5px" id="changevcode">换一张</a>
</div>
<p class="text"><span id="error-show" class="error-show"></span></p>
<input type="button" value="登录" class="button1" id="btn"/>
</form>
</div>
</body>
</html>
运行截图: