【登录验证码】动态与静态验证码实现逻辑
目录
1、需要设计一个静态验证码实体类
随机生成字母数字的工具类
Captcha验证码类
动画gif实体类
验证码前端接口
前言
要实现一个静态的简单地字母数字的验证码登录,同时也实现一个划拉式的验证码动态匹配的实现逻辑;
1、需要设计一个静态验证码实体类
随机生成字母数字的工具类
/**
*随机工具类 作为一个随机生成字母数字的工具类
* @version:1.0
*/
public class Randoms
{
private static final Random RANDOM = new Random();
//定义验证码字符.去除了O和I等容易混淆的字母
public static final char ALPHA[]={'A','B','C','D','E','F','G','H','G','K','M','N','P','Q','R','S','T','U','V','W','X','Y','Z'
,'a','b','c','d','e','f','g','h','i','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7','8','9'};
/**
* 产生两个数之间的随机数
* @param min 小数
* @param max 比min大的数
* @return int 随机数字
*/
public static int num(int min, int max)
{
return min + RANDOM.nextInt(max - min);
}
/**
* 产生0--num的随机数,不包括num
* @param num 数字
* @return int 随机数字
*/
public static int num(int num)
{
return RANDOM.nextInt(num);
}
public static char alpha()
{
return ALPHA[num(0, ALPHA.length)];
}
}
Captcha验证码类
/**
* 验证码抽象类,暂时不支持中文,目前仅仅支持随机的字母数字
* @version:1.0
*/
@Data
public abstract class Captcha extends Randoms {
/**
* 字体
*/
protected Font font = new Font("Verdana", Font.ITALIC | Font.BOLD, 28);
// 验证码随机字符长度
/**
* 验证码随机字符长度
*/
protected int len = 5;
/**
* 宽度
*/
protected int width = 150;
// 验证码显示高度
/**
* 高度
*/
protected int height = 40;
/**
* 随机字符串
*/
private String chars = null;
/**
* 生成随机字符数组
*
* @return 字符数组
*/
protected char[] alphas() {
char[] cs = new char[len];
for (int i = 0; i < len; i++) {
cs[i] = alpha();
}
chars = new String(cs);
return cs;
}
/**
* 给定范围获得随机颜色
*
* @return Color 随机颜色
*/
protected Color color(int fc, int bc) {
if (fc > INT_TWO_FIVE_FIVE) {
fc = INT_TWO_FIVE_FIVE;
}
if (bc > INT_TWO_FIVE_FIVE) {
bc = INT_TWO_FIVE_FIVE;
}
int r = fc + num(bc - fc);
int g = fc + num(bc - fc);
int b = fc + num(bc - fc);
return new Color(r, g, b);
}
/**
* 验证码输出,抽象方法,由子类实现
*
* @param os 输出流
*/
public abstract void out(OutputStream os);
/**
* 获取随机字符串
*
* @return string
*/
public String text() {
return chars;
}
}
/**
* int常量
*/
public static final int INT_ZERO = 0;
public static final int INT_ONE = 1;
public static final int INT_TWO = 2;
public static final int INT_THREE = 3;
public static final int INT_FIVE = 5;
public static final int INT_SERVEN = 7;
public static final int INT_TWO_FIVE_FIVE = 255;
动画gif实体类
/**
* <p>Gif验证码类</p>
* @version:1.0
*/
public class GifCaptcha extends Captcha
{
public GifCaptcha()
{
}
public GifCaptcha(int width,int height){
this.width = width;
this.height = height;
}
public GifCaptcha(int width,int height,int len){
this(width,height);
this.len = len;
}
public GifCaptcha(int width,int height,int len,Font font)
{
this(width,height,len);
this.font = font;
}
@Override
public void out(OutputStream os)
{
try
{
// gif编码类,这个利用了洋人写的编码类,所有类都在附件中
GifEncoder gifEncoder = new GifEncoder();
//生成字符
gifEncoder.start(os);
gifEncoder.setQuality(180);
gifEncoder.setDelay(100);
gifEncoder.setRepeat(0);
BufferedImage frame;
char[] rands =alphas();
Color fontcolor[]=new Color[len];
for(int i=0;i<len;i++)
{
fontcolor[i]=new Color(20 + num(110), 20 + num(110), 20 + num(110));
}
for(int i=0;i<len;i++)
{
frame=graphicsImage(fontcolor, rands, i);
gifEncoder.addFrame(frame);
frame.flush();
}
gifEncoder.finish();
}finally
{
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 画随机码图
* @param fontcolor 随机字体颜色
* @param strs 字符数组
* @param flag 透明度使用
* @return BufferedImage
*/
private BufferedImage graphicsImage(Color[] fontcolor,char[] strs,int flag)
{
BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
//或得图形上下文
//Graphics2D g2d=image.createGraphics();
Graphics2D g2d = (Graphics2D)image.getGraphics();
//利用指定颜色填充背景
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
AlphaComposite ac3;
int h = height - ((height - font.getSize()) >>1) ;
int w = width/len;
g2d.setFont(font);
for(int i=0;i<len;i++)
{
ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(flag, i));
g2d.setComposite(ac3);
g2d.setColor(fontcolor[i]);
g2d.drawOval(num(width), num(height), 5+num(10), 5+num(10));
g2d.drawString(strs[i]+"", (width-(len-i)*w)+(w-font.getSize())+1, h-4);
}
g2d.dispose();
return image;
}
/**
* 获取透明度,从0到1,自动计算步长
* @return float 透明度
*/
private float getAlpha(int i,int j)
{
int num = i+j;
float r = (float)1/len,s = (len+1) * r;
return num > len ? (num *r - s) : num * r;
}
}
验证码前端接口
@Autowired
private ZaptchaProperties captchaProperties;
@Autowired
private Producer producer;
@Autowired
private RedisUtil redisUtil;
/**
* 生成gif验证码
*/
@RequestMapping("/gif")
public void indexGif(HttpServletRequest request, HttpServletResponse response) {
String captchaId = request.getParameter("captchaId");
if (ToolUtil.isEmpty(captchaId)) {
throw new ServiceException(ExceptionEnum.REQUEST_NULL);
}
Captcha gifCaptcha = new GifCaptcha(captchaProperties.getCaptchaWidth(),
captchaProperties.getCaptchaHigh(),
captchaProperties.getCaptchaLen());
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg
response.setContentType("image/gif");
//输出
//存入Session
OutputStream out = null;
try {
out = response.getOutputStream();
gifCaptcha.out(out);
redisUtil.set(captchaProperties.getCaptchaSessionKey() + captchaId, gifCaptcha.text().toLowerCase(), captchaProperties.getCaptchaSessionExpired());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 生成普通验证码
*/
@RequestMapping("pic")
public void indexPic(HttpServletRequest request, HttpServletResponse response) {
String captchaId = request.getParameter("captchaId");
if (ToolUtil.isEmpty(captchaId)) {
throw new ServiceException(ExceptionEnum.REQUEST_NULL);
}
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg
response.setContentType("image/jpeg");
// create the text for the image
String capText = producer.createText();
// create the image with the text
BufferedImage bi = producer.createImage(capText);
ServletOutputStream out = null;
try {
out = response.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
// write the data out
try {
ImageIO.write(bi, "jpg", out);
redisUtil.set(captchaProperties.getCaptchaSessionKey() + captchaId, capText.toLowerCase(), captchaProperties.getCaptchaSessionExpired());
} catch (IOException e) {
e.printStackTrace();
}
try {
try {
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
还没有评论,来说两句吧...