版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Point9/article/details/84959875
一、功能分析
在登录页面实现图形验证码的功能
具体实现:(思路分析)
1、登录页面中通过img标签调用封装的工具类VerifyUtil(说明登录页面用jsp实现,为了后期接收响应结果)
2、编写工具类VerifyUtil,具体功能:
- 生成四个随机字符(数字,大写字母或小写字母)
- 实例化BufferedImage对象绘制缓存图片,调用对象的getGraphics()方法创建画笔
- 设置图片背景颜色,确定图片位置和大小
- 封装getRandomColor()方法,实现字符和干扰线颜色随机
- 封装getRandomFont()方法,实现字符的字体随机
- 画随机字符和干扰线
- 调用ImageIO.write()方法,返回图片给前端
3、前端功能实现:
通过JavaScript调用VerifyUtil工具类,实现点击图片更换验证码(易错,下面会具体分析)
4、对于验证码的验证,在工具类中存到session中,在在逻辑层实现验证(seeion 中的数据和用户输入的数据对比)
二、源码实现
1、登录页面 login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户登录</title>
<link href="css/login.css" rel="stylesheet">
<script type="text/javascript">
function change() {
var img = document.getElementById("img");
/* 访问时带参数,避免出现缓存 */
img.src = "verify?date=" + new Date();
}
</script>
</head>
<body>
<div class="login">
<a href="#" class="choose left">账号登录</a> <span style="color: #e0e0e0">|</span>
<a href="#" class="choose right">扫码登录</a>
<%
//String msg = (String)session.getAttribute("msg");
String msg = (String) request.getAttribute("msg");
%>
<br>
<%=msg == null ? "" : msg%>
<form action="login" method="post">
<input name="uname" type="text" placeholder="用户名" id="login-text">
<input name="pwd" type="password" placeholder="密码" id="login-pwd">
<input name="code" type="text" placeholder="验证码" id="login-code">
<img id="img" src="verify" onclick="change()">
<input type="submit" value="登录" id="login-sub">
</form>
<span class="forget"> <a href="register.jsp">注册账号</a> <span>|</span>
<a href="forget.jsp">忘记密码?</a></span>
</div>
</body>
</html>
2、页面的相关样式
/* ----------元素位置布局---------- */
* {
margin: 0;
padding: 0;
}
.login {
width: 400px;
box-shadow: 0 0 15px 3px rgba(51, 51, 51, 0.53);
margin: 20px auto 0 auto;
/* border: 1px solid aqua; */
text-align: center;
}
#login-text,
#login-pwd,
#login-img {
width: 350px;
height: 30px;
display: inline-block;
margin-left: auto;
margin-right: auto;
}
#login-sub {
width: 364px;
height: 30px;
display: inline-block;
margin-left: auto;
margin-right: auto;
}
/* ----------样式设计---------- */
a {
color: black;
text-decoration: none;
}
.choose {
display: inline-block;
margin-top: 30px;
font-size: 22px;
}
.left {
color: #f56600;
margin-right: 15px;
}
.right {
margin-left: 15px;
}
#login-text,
#login-pwd {
padding: 8px 5px;
font-size: 16px;
/* box-sizing: border-box; */
outline: none;;
}
#login-text {
margin-top: 35px;
}
#login-pwd {
margin-top: 15px;
}
#login-sub {
height: 50px;
margin-top: 15px;
border: none;
outline: none;
font-size: 20px;
background-color: #f56600;
color: white;
}
.forget {
display: inline-block;
margin-top: 15px;
font-size: 13px;
color: #e0e0e0;
}
.forget a {
color: #999;
}
.forget a:hover {
text-decoration: underline;
}
fieldset {
display: inline-block;
width: 364px;
margin-top: 80px;
color: #999;
border: none;
border-top: 1px solid #999
}
#img {
float: right;
margin-top: 15px;
margin-right: 20px;
}
#login-code {
margin-top: 15px;
padding: 8px 5px;
font-size: 16px;
width: 220px;
height: 30px;
display: inline-block;
}
3、工具类VerifyUtil.java
package com.point9.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class VerifyUtil extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 验证码字符集
char[] chars = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
// 字符数量
int size = 4;
// 干扰线数量
int lines = 5;
// 宽度
int width = 110;
// 高度
int height = 50;
// 字体大小
int font_size = 30;
//1、创建缓存图片 参数3:图片类型:RGB
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
//2、创建画笔,绘制图形
Graphics graphics = image.getGraphics();
//3、设置背景颜色
graphics.setColor(Color.LIGHT_GRAY);//颜色
//4、绘制背景(此处占用了缓存图片的全部内容)
graphics.fillRect(0, 0, width, height);
//5、画随机字符
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < size; i++) {
//取随机字符索引
int n = random.nextInt(chars.length);
//设置随机颜色
graphics.setColor(getRandomColor());
//设置随机字体和相关样式
String font_family = getRandomFont();
graphics.setFont(new Font(font_family, Font.BOLD, font_size));
//画字符
graphics.drawString(chars[n]+"",i * width / size, height * 2 / 3);
//记录字符
sb.append(chars[n]);
}
//把字符存储到session中,便与登录时验证
req.getSession().setAttribute("code", sb.toString());
//6、设置干扰线
for(int i=0;i<lines;i++) {
// 设置随机颜色
graphics.setColor(getRandomColor());
// 随机画线
graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
}
//7、返回到前端img中 参数1:缓存图片 参数2:输出格式 参数3:输出流
try {
ImageIO.write(image, "jpeg", resp.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 随机取色
*/
public static Color getRandomColor() {
Random ran = new Random();
Color color = new Color(ran.nextInt(256),
ran.nextInt(256), ran.nextInt(256));
return color;
}
/**
* 随机字体
*/
public static String getRandomFont() {
String[] fonts = new String[] {"微软雅黑","宋体","Serif","Cursive","Fantasy"};
int i = (int) (Math.random()*(fonts.length));
String font=fonts[i];
return font;
}
}
4、登录验证LoginServlet.java
package com.Point9.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class LoginServlet
*/
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1、处理中文乱码问题
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 2、获取请求信息
String uname = request.getParameter("uname");
String pwd = request.getParameter("pwd");
String code = request.getParameter("code");
// 3、处理请求
String imgCode =(String) request.getSession().getAttribute("code");
if(!imgCode.equalsIgnoreCase(code)) {//此处忽略大小写
response.getWriter().write("验证码错误~");
return;
}
/*
* 遍历集合,如果信息匹配则登录成功
* 此处自行更改,验证用户名和密码是否正确
*/
List<Student> list = DBCenter.list;
boolean flag = false;
for (Student st : list) {
if (st.getUname().equals(uname)&&st.getPwd().equals(pwd)) {
flag = true;
break;
}
}
// 4、响应处理结果
if(flag) {
response.getWriter().write("登录成功!");
}else {
request.setAttribute("msg", "request+请求转发:登录失败!");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
写在最后,此处是忽略大小写的(equalsIgnoreCase)!
"A".equalsIgnoreCase("a");比较时直接忽略大小写
str.toLowerCase()转小写,str.toUpperCase()转大写
本博客的全部源码,我已经放Git上了,供大家交流学习。https://gitee.com/point9/verify_util
最后福利到,欢迎有兴趣的朋友一起交流成长。
Web全栈技术交流
点击链接加入群聊【Web全栈交流群】:https://jq.qq.com/?_wv=1027&k=5rnUzsF