验证码的生成,这个在Web登陆系统中,我像大家都很常见了,所以我这里简单的介绍两种方法来实现这样的操作。
情况一:纯粹通过JSP来进行实现
方法一:
描述:纯粹通过JSP来完成验证码的实现
验证码显示的JSP代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
验证码
刷新
验证码生成的JSP代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Random"%>
<%@ page import="java.io.OutputStream"%>
<%@ page import="java.awt.Color"%>
<%@ page import="java.awt.Font"%>
<%@ page import="java.awt.Graphics"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.imageio.ImageIO"%>
<%
//设置验证码宽度
int width = 60;
//设置验证码高度
int height = 32;
//创建一个image对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//创建一个画板
Graphics g = image.getGraphics();
//设置背景颜色
g.setColor(new Color(0xDCDCDC));
//填充一个矩形
g.fillRect(0, 0, width, height);
//画矩形框的边框颜色
g.setColor(Color.black);
//绘制一个矩形
g.drawRect(0, 0, width - 1, height - 1);
//创建一个随机对象,用于获取产生随机验证码
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
System.out.print(hash1);
// 为了使验证码不易于区分,所以这里就产生50个随机的圆点,来进行迷惑
for (int i = 0; i < 50; i++) {
int x = rdm.nextInt(width);
int y = rdm.nextInt(height);
//绘制椭圆
g.drawOval(x, y, 0, 0);
}
// 截取产生的验证码的前四位(这个根据自己需要进行设置)
String capstr = hash1.substring(0, 4);
//将生成的验证码存入session
session.setAttribute("validateCode", capstr);
//绘制验证码的颜色
g.setColor(new Color(0, 100, 0));
//设置字体
g.setFont(new Font("Candara", Font.BOLD, 24));
g.drawString(capstr, 8, 24);
g.dispose();
//输出图片
response.setContentType("image/jpeg");
out.clear();
out = pageContext.pushBody();
OutputStream strm = response.getOutputStream();
ImageIO.write(image, "jpeg", strm);
strm.close();
%>
情况一:基于标准的Servlet的形式开发模式(非框架)
方法二:
Servlert代码:
package hnu.scw.properce;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
/*
* 演示验证码的生成到html中来进行显示
*
*/
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletYanZhengMa extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
String code = drawImg(output);
//在这里还可以将验证码的信息保存到session中,方便进行登陆的时候判断是否正确
try {
ServletOutputStream out = response.getOutputStream();
output.writeTo(out);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//绘制验证码
private String drawImg(ByteArrayOutputStream output) {
String code = "";
for (int i = 0; i < 4; i++) {
code += randomChar();
}
int width = 70;
int height = 25;
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Font font = new Font("Times New Roman", Font.PLAIN, 20);
Graphics2D g = bi.createGraphics();
g.setFont(font);
Color color = new Color(66, 2, 82);
g.setColor(color);
g.setBackground(new Color(226, 226, 240));
g.clearRect(0, 0, width, height);
FontRenderContext context = g.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(code, context);
double x = (width - bounds.getWidth()) / 2;
double y = (height - bounds.getHeight()) / 2;
double ascent = bounds.getY();
double baseY = y - ascent;
g.drawString(code, (int) x, (int) baseY);
g.dispose();
try {
ImageIO.write(bi, "jpg", output);
} catch (IOException e) {
e.printStackTrace();
}
return code;
}
//生成四位数的验证码(这里就是在字母和数字之间产生,如果你需要更多的符号,那么就自己添加在String中就可以了哦)
private char randomChar() {
Random r = new Random();
String s = "ABCDEFGHJKLMNPRSTUVWXYZ0123456789";
return s.charAt(r.nextInt(s.length()));
}
}
Html代码:(页面简单点哈,能明白意思就可以了!!)
Insert title here
备注:请注意我写的注释代码,这个地方非常非常重要!!!!!!!!!!!!!!!
方法三:(类似方法一,但是生成的方式有所变化,可以根据需要进行选择)
Servlert代码:
package hnu.scw.properce;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
/*
* 演示验证码的生成到html中来进行显示
*
*/
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletYanZhengMa extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
getYanZhengMa(response); //调用方法
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/*
* 生成验证码
*/
private void getYanZhengMa(HttpServletResponse response) {
//设置一下颜色数组,为了验证码更加难辨认
Color[] yanse = {Color.RED ,Color.BLACK ,Color.GREEN , Color.BLUE};
//初始化验证码的宽和高
int width = 100 ;
int height = 60;
//初始化图片缓冲器
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) ;
//初始化画笔
Graphics gp = bi.getGraphics(); //这里是用图片来进行初始化,否则不知道是画在哪里
//设置画笔颜色
gp.setColor(Color.RED);
//画一个矩形的外框
gp.drawRect(0, 0, width, height);
//设置矩形填充的颜色
gp.setColor(Color.YELLOW);
//填充背景(下面是从1,1开始填充,如果从0,0开始,那么外框也会被修改了,后面-2也是同理)
gp.fillRect(1, 1, width-2, height-2);
//生成要填充的内容
Random random = new Random();
//设置验证码的干扰线(这是为了效果来进行开发的,可以没有)
gp.setColor(Color.BLUE);
//画30条干扰线
for(int i=0 ; i<30 ;i++){
gp.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
//下面的是画点
//gp.drawOval(random.nextInt(width), random.nextInt(height), 2, 2);
}
//设置填充的内容的颜色
gp.setColor(Color.RED);
//设置填充内容的大小
gp.setFont(new Font("幼圆", Font.BOLD + Font.ITALIC, 20));
//如果填充的内容要为中文的时候,需要这样处理
String content ="全国我觉得嘎斯的获奖情况大手笔的吧区隔化akshldeqw";
//要把上面的转为unicode编码,因为如果浏览器不支持中文的话就会出现乱码,如果在国内的话则没有什么影响
//用在线工具转也可以,但最好用代码来进行转变,因为以后开发肯定是动态的一种方式最好
//content ="\u5168\u56fd\u6211\u89c9\u5f97\u560e\u65af\u7684\u83b7\u5956\u60c5\u51b5\u5927\u624b\u7b14\u7684\u5427\u533a\u9694\u5316\u0061\u006b\u0073\u0068\u006c\u0064\u0065\u0071\u0077";
for(int i =0 ; i < 4 ;i++){
//gp.setColor(yanse[random.nextInt(3)]);设置填充的颜色随即化(为了验证码更复杂)
char c =content.charAt(random.nextInt(content.length()));
gp.drawString(c + "", 20 + 20*i, 30); //开始填充内容和位置
}
//如果想要验证码是数字的,则填充的内容为数字(生成四个数字)
// for(int i=0 ; i<4 ;i++){
// int number = random.nextInt(10); //生成10以内的数字
// gp.drawString(number + "", 20 + 20*i, 30); //开始填充内容和位置
// }
//设置不要缓存
response.setHeader("Expires", -1+"");
response.setHeader("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache");
//将验证码显示到对应的位置
try {
ImageIO.write(bi, "jpg", response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Html代码:
Insert title here
总结:上面就是三种方法了,是不是很简单,其实不是想象的那么难。。当然,我这没有把登陆写进去,这个自己添加就可以了,只是注意一点就是在生成验证码的时候,要把验证码的字符保存到session中,否则在登陆判断验证码是否正确就没什么好方法啦。。。当然,你有其他的解决办法都可以哦~~
下面利用一个相对完整的Demo来进行演示(包含了登陆的判断了哦!!!)
情况二;基于SpringMVC框架
生成验证码的controller类的代码:
package com.mbfw.controller.system.secCode;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.mbfw.util.Const;
/**
* 类名称:SecCodeController 作者单位:
*
* @version
*/
@Controller
@RequestMapping("/code")
public class SecCodeController {
@RequestMapping
public void generate(HttpServletResponse response) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
String code = drawImg(output);
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
session.setAttribute(Const.SESSION_SECURITY_CODE, code);
try {
ServletOutputStream out = response.getOutputStream();
output.writeTo(out);
} catch (IOException e) {
e.printStackTrace();
}
}
private String drawImg(ByteArrayOutputStream output) {
String code = "";
for (int i = 0; i < 4; i++) {
code += randomChar();
}
int width = 70;
int height = 25;
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Font font = new Font("Times New Roman", Font.PLAIN, 20);
Graphics2D g = bi.createGraphics();
g.setFont(font);
Color color = new Color(66, 2, 82);
g.setColor(color);
g.setBackground(new Color(226, 226, 240));
g.clearRect(0, 0, width, height);
FontRenderContext context = g.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(code, context);
double x = (width - bounds.getWidth()) / 2;
double y = (height - bounds.getHeight()) / 2;
double ascent = bounds.getY();
double baseY = y - ascent;
g.drawString(code, (int) x, (int) baseY);
g.dispose();
try {
ImageIO.write(bi, "jpg", output);
} catch (IOException e) {
e.printStackTrace();
}
return code;
}
private char randomChar() {
Random r = new Random();
String s = "ABCDEFGHJKLMNPRSTUVWXYZ0123456789";
return s.charAt(r.nextInt(s.length()));
}
}
备注:其实这个和在标准的Servlet中的形式是一样的,只是用了SpringMVC的模式来编写而已,所以知道Servlet的方法,用其他的框架来写都会了!!!
jsp代码:(这里写个比较完整的)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
%>
${pd.SYSNAME}
备注:这里面的css和JS的引用,我没有写出来了,都是比较简单的,主要是用了jQuery还有Bootstap这两个插件的内容。如果只是想测试的话,只是样式不好看而已,都是次要的,关键在于功能可以就好了哈!!!
验证登陆的controller层代码(用shiro框架的权限认证方法,但是可以省略,根据需要进行自己修改):
/**
* 请求登录,验证用户
*/
@RequestMapping(value = "/login_login", produces = "application/json;charset=UTF-8")
@ResponseBody
public Object login() throws Exception {
Map map = new HashMap();
PageData pd = new PageData();
pd = this.getPageData();
String errInfo = "";
String KEYDATA[] = pd.getString("KEYDATA").replaceAll("qq123456789mbfw", "").replaceAll("QQ123456789mbfw", "").split(",mbfw,");
boolean ismobile = false;
if(pd.getString("ismobile")!=null && pd.getString("ismobile").toString().equals("true"))
ismobile = true;
if (null != KEYDATA && KEYDATA.length == 3) {
// shiro管理的session
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
String sessionCode = (String) session.getAttribute(Const.SESSION_SECURITY_CODE); // 获取session中的验证码
String code = KEYDATA[2];
if (null == code || "".equals(code)) {
errInfo = "nullcode"; // 验证码为空
} else {
String USERNAME = KEYDATA[0];
String PASSWORD = KEYDATA[1];
pd.put("USERNAME", USERNAME);
if ((Tools.notEmpty(sessionCode) && sessionCode.equalsIgnoreCase(code)) || ismobile) {
String passwd = new SimpleHash("SHA-1", USERNAME, PASSWORD).toString(); // 密码加密
pd.put("PASSWORD", passwd);
pd = userService.getUserByNameAndPwd(pd);
if (pd != null) {
pd.put("LAST_LOGIN", DateUtil.getTime().toString());
userService.updateLastLogin(pd);
User user = new User();
user.setUSER_ID(pd.getString("USER_ID"));
user.setUSERNAME(pd.getString("USERNAME"));
user.setPASSWORD(pd.getString("PASSWORD"));
user.setNAME(pd.getString("NAME"));
user.setRIGHTS(pd.getString("RIGHTS"));
user.setROLE_ID(pd.getString("ROLE_ID"));
user.setLAST_LOGIN(pd.getString("LAST_LOGIN"));
user.setIP(pd.getString("IP"));
user.setSTATUS(pd.getString("STATUS"));
user.setUser_Permission((Integer)pd.get("user_Permission"));
user.setSuperior_organization_name(pd.getString("superior_organization_name"));
user.setOrganization_name(pd.getString("organization_name"));
session.setAttribute(Const.SESSION_USER, user);
session.setAttribute(Const.IS_MOBILE, ""+ismobile);
session.removeAttribute(Const.SESSION_SECURITY_CODE);
// shiro加入身份验证
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(USERNAME, PASSWORD);
try {
subject.login(token);
} catch (AuthenticationException e) {
errInfo = "身份验证失败!";
}
} else {
errInfo = "usererror"; // 用户名或密码有误
}
} else {
errInfo = "codeerror"; // 验证码输入有误
}
if (Tools.isEmpty(errInfo)) {
errInfo = "success"; // 验证成功
}
}
} else {
errInfo = "error"; // 缺少参数
}
map.put("result", errInfo);
return AppUtil.returnObject(new PageData(), map);
}
验证通过后,显示系统的主界面controller层代码:
@RequestMapping(value = "/main/index")
public ModelAndView login_index() {
ModelAndView mv = new ModelAndView();
mv.setViewName("jsp/login_success.jsp");
return mv;
}
登陆成功后显示的界面html代码----login_success.jsp
Insert title here
欢迎你
总结:好了,上面三种方法应该能够满足需要验证码的这个需求了,并且也给了一个完整的Demo进行演示。总的来说不是很难验证码背景图片下载,但是想着用得多,所以我这就写篇文章来记录一下好了。如果有更好的方法验证码背景图片下载,可以留言的哦!!我都会关注的啦。。大家一起。。加油加油。。
版权声明
本文仅代表作者观点。
本文系作者授权发表,未经许可,不得转载。
发表评论