第1关:使用Servlet生成验证码
相关知识
为什么要有验证码,什么是验证码
我们经常需要在网站或者应用程序中填写验证码,不过作为用户而言其实我们一点都不喜欢验证码,因为有时候老容易填错。
为什么这个影响用户体验的东西还是一直存在呢?肯定是有道理的。
一个网站除了我们人操作电脑可以登录之外,使用JavaScript
代码和一些脚本语言也是可以登录的,但是我们开发网站是给人用的而不是给机器使用的,我们想象一个网站如果没有验证码,我们只需要编写一段脚本就可以无限次数的登陆某个网站,这样无数次的尝试就可以暴力破解用户的密码,如果是注册行为那就会给网站制造很多垃圾信息,这个就会对该网站造成极大的资源浪费,严重的可能会让这个网站崩溃,所以就有了验证码。
说白了,验证码就是用来判断是人在操作还是机器在操作。
如何使用Servlet生成验证码
在Java
中我们可以在Web
项目中使用Servlet
来生成验证码,流程是:前端请求验证码servlet
对应的地址,后端servlet
收到请求,生成一串字符作为验证码,存入到Session
中,最后将验证码作为一张图片返回给前端。前端填写了验证码提交到服务器来验证。
我们看一个示例,你也可以根据这个示例在右侧编辑器中一步一步实现验证码的功能。
项目和servlet
已经创建好了,我们首先在web.xml
文件中注册servlet
。如下:
在servlet
的doGet()
方法中编写代码实现生成图片验证码:
分为如下步骤:
-
定义图像数据缓冲区(
BufferedImage
); -
创建图片对象;
-
创建绘制工具(
Graphics
); -
生成随机数,存入到
session
中; -
使用
Graphics
绘制图形; -
将验证码通过图像输出流(
ImageIO
)输出到客户端; -
最后输入验证码地址即可访问单验证码。
具体代码如下:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 使用验证码的步骤
// 定义图片的宽高
int height = 20;
int width = 60;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘图工具
Graphics graphics = image.getGraphics();
// 绘制矩形
graphics.setColor(getRandColor());
// 绘制矩形背景 前两个参数 是 x y的坐标
graphics.fillRect(0, 0, width, height);
// 设置文字的颜色 为白色
graphics.setColor(Color.WHITE);
String yzm = "";
// 生成四个随机数字并且画在图片上
for (int i = 1; i <= 4; i++) {
// 生成随机数字并且显示到页面上
int number = new Random().nextInt(10);
yzm += number;
graphics.drawString(number + "", 10 * i, 10);
}
// 将验证码放入Httpsession中
HttpSession session = req.getSession();
session.setAttribute("sessionYzm", yzm);
// 将验证码图片输出到客户端
ImageIO.write(image, "jpg", resp.getOutputStream());
}
// 获取随机颜色
private Color getRandColor() {
int red = new Random().nextInt(255);
int green = new Random().nextInt(255);
int blue = new Random().nextInt(255);
return new Color(red, green, blue);
}
/********* Begin *********/
//请在此编写生成验证码的代码
int height=20;
int width=60;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//绘图工具
Graphics gra=image.getGraphics();//绘制矩形
gra.setColor(getRandColor());
gra.fillRect(0,0,width,height);
gra.setColor(Color.WHITE);
String yzm="";
for(int i=1;i<=4;i++){
int num = new Random().nextInt(10);
yzm+=num;
gra.drawString(num+"",10*i,10);
}
HttpSession ses=req.getSession();
ses.setAttribute("sessionYzm",yzm);
ImageIO.write(image,"jpg",resp.getOutputStream());
/********* End *********/
第2关:用户登录时校验验证码是否正确
相关知识
登录功能
我们经常在登录注册的时候填写验证码,本关我们就来实现登录功能。
首先我们来理解验证码校验的基本流程:
上图展示了一个用户填写验证码的基本流程,用户打开网页显示服务端生成的验证码,点击“看不清楚”标签可以重新生成,这个时候会从新请求服务端数据,服务端用Session
来保存验证码信息。
当用户点击确认按钮的时候,我们就需要对用户通过表单提交的验证码进行校验了,这个时候服务端获取Session
保存的验证码信息和用户提交的验证码数据进行校验如果两者一致则校验通过。
这就是一个完整的验证码流程了。
我们可以将验证码的流程总结为:
前端表单登陆 => 后端获取到验证码校验 => 前端收到后端的响应。
借下来我们来实现这个过程。
前端实现
我们创建一个登录表单,代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<form action="loginServlet">
用户名:
<input type="text" name="username">
<br>
密 码:
<input type="text" name="password">
<br>
验证码:
<input type="text" name="verifycode" id="yzm">
<!-- src填servlet的地址就能显示网络上的图片 -->
<a href="javascript:reload()"><img id="yzmImg" src="code"/> </a>
<br>
<input type="submit" value="提交">
</form>
</body>
<script type="text/javascript">
//重新加载验证码
function reload() {
var img = document.getElementById("yzmImg");
img.src = "code?" + new Date().getTime();
}
</script>
</html>
效果如下:
后端校验
前端页面写好之后我们就可以验证在后端编写代码来验证,表单传递过来的参数是否正确了。
步骤如下:
-
接收用户传递的参数:
username,password,verifycode
; -
判断验证码是否正确;
-
如果验证码正确则判断用户名和密码是否正确。否则提示客户端验证码错误;
-
用户名密码正确,回传给客户端“登录成功”。
校验验证码的核心代码如下:
/********* Begin *********/
//请在此进行登录校验
PrintWriter w=resp.getWriter();
String veri=req.getParameter("verifycode");
String user=req.getParameter("username");
String pass=req.getParameter("password");
HttpSession sess=req.getSession();
String realCode=(String) sess.getAttribute("sessionYzm");
if(!veri.equals(realCode)){
w.write("验证码错误");
}else if(user.equals("admin")&&pass.equals("admin123")){
w.write("登录成功");
}else{
w.write("登录失败");
}
/********* Begin *********/
第3关:使用Kaptcha组件生成验证码
相关知识
之前两关我们已经了解了验证码的制作流程,不过我们在开发中一般不会去自己从零开始编写验证码,而是会使用到开源的组件,本关我们就来使用Kaptcha
来生成验证码,并且编写一个页面校验用户的验证码是否输入正确。
Kaptcha 组件的使用
先来看要实现的效果:
首先制作用户填写验证码的页面captchacode.jsp
<script type="text/javascript">
function reloadCode() {
var date = new Date().getTime();
document.getElementById("code").src = "<%=request.getContextPath() %>/imageKaptcha?d="+date;
}
</script>
<form action="checkCaptcha.jsp" method = "post">
<img alt="验证码" src="imageKaptcha" id = "code"><a href = "javascript:reloadCode();">看不清</a>
<input type = "text" name = "captcha">
<input type = "submit" value = "submit">
</form>
接着我们写一个检查验证码输入是否正确的类checkCaptchaServlet.java
request.setCha\fracterEncoding("utf-8");
// 获取Kaptcha jar包里面的KAPTCHA_SESSION_KEY
String trueCaptcha = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
String inputCaptcha = request.getParameter("captcha");
if(trueCaptcha.toLowerCase().equals(inputCaptcha.toLowerCase())) {
out.write("验证码输入正确");
} else {
out.write("验证码输入错误");
}
然后配置好web.xml
就ok
了。
下面我们来看看怎么配置web.xml
<servlet>
<servlet-name>myCaptcha</servlet-name>
<!-- jar中的 KaptchaServlet的路径-->
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<!--配置kaptcha 校验验证码是否正确的 servlet-->
<servlet>
<servlet-name>CheckCaptcha</servlet-name>
<servlet-class>com.servlet.CheckCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myCaptcha</servlet-name>
<!-- 对于index.jsp中img的src -->
<url-pattern>/imageKaptcha</url-pattern>
</servlet-mapping>
<!--第三关:配置kaptcha 校验验证码的 servlet-->
<servlet-mapping>
<servlet-name>CheckCaptcha</servlet-name>
<url-pattern>/checkCaptcha</url-pattern>
</servlet-mapping>
做完上述步骤之后,运行项目,打开网页,即可查看验证码。
扩展:Kaptcha
还有很多其他的设置可以实现图片边框,边框颜色,中文验证码等操作,限于篇幅在这里就不在赘述。
// CheckCaptchaServlet.java
/********* Begin *********/
//校验kaptcha 验证码是否正确
//获取Kaptcha jar包里面的KAPTCHA_SESSION_KEY
PrintWriter w=resp.getWriter();
HttpSession sess=req.getSession();
String TC=(String) sess.getAttribute(Constants.KAPTCHA_SESSION_KEY);
String IC=req.getParameter("captcha");
if(TC.toLowerCase().equals(IC.toLowerCase())){
w.write("验证码输入正确");
}else{
w.write("验证码输入错误");
}
/********* End *********/
// captchacode.jsp
<!--------- End --------->
<form action="checkCaptcha.jsp" method="post">
<img alt="验证码" src="imageKaptcha" id="code"><a href="javascript:reloadCode();">看不清</a>
<input type="text" name="captcha">
<input type="submit" value="submit">
<!--------- Begin --------->