可以旋转文字的验证码

直接上图,验证码可以设置字符个数,字符颜色,背景颜色,旋转角度,新的字体。

请注意加载新字体那一块代码,一定要注册一下,不然带不出文字。

自己看代码吧。。。

package com.ukWord.servlet;

import com.ukWord.util.AppConst;
import org.apache.commons.lang3.StringUtils;
import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;

public class SecurityCodeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private int width = 173;
	private int height = 24;
	private int fontSize = height;
	private int securityCodeLength = 4;
    private int interferingLineCount = 20;
    private Font font = new Font("Times New Romans", Font.BOLD, fontSize);
	private String charStr = "A0KLBMNC2PD3QRE4STF5UVG6WXH7YZ8J9秋花惨淡秋草黄耿耿秋灯秋夜长已觉秋窗秋不尽那堪风雨助凄凉";
	private String[] chars;
	private int charWidth;
	private int charHeight;

	@Override
	public void init() throws ServletException {
		try{
			Properties config = new Properties();
			config.load(SecurityCodeServlet.class.getResourceAsStream("/config.properties"));

			String withStr = config.getProperty("security.code.width");
			if(StringUtils.isNotEmpty(withStr)){
				this.width = Integer.parseInt(withStr);
			}

			String securityCodeLengthStr = config.getProperty("security.code.length");
			if(StringUtils.isNotEmpty(securityCodeLengthStr)){
				this.securityCodeLength = Integer.parseInt(securityCodeLengthStr);
			}

			String interferingLineCountStr = config.getProperty("security.code.interfering.line.count");
			if(StringUtils.isNotEmpty(interferingLineCountStr)){
				this.interferingLineCount = Integer.parseInt(interferingLineCountStr);
			}

			String fontStr = config.getProperty("security.code.fontStyle");
			if(StringUtils.isNotEmpty(fontStr)){
				if(!StringUtils.contains(fontStr, ".ttf")){
					this.font = new Font(fontStr, Font.BOLD, fontSize);
				}else{
					this.font = registerFont(fontStr);
				}

			}

			String charsStr = config.getProperty("security.code.text");
			if(StringUtils.isNotEmpty(charsStr)){
				this.charStr = charsStr;
			}
			this.chars = new String[charsStr.length()];
			for(int i = 0; i < charsStr.length(); i++){
				this.chars[i] = String.valueOf(charsStr.charAt(i));
			}

			FontMetrics fontMetrics = FontDesignMetrics.getMetrics(this.font);
			this.charWidth = fontMetrics.stringWidth("M");
			this.charHeight = fontMetrics.getHeight();

		}catch(Exception e){
			e.printStackTrace();
		}
	}

    @Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			Random random = new Random();
			BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = buffImg.createGraphics();
			g.setFont(this.font);

			//画背景
			g.setColor(this.getRandomColor(random, 200, 55));
			g.fillRect(0, 0, width, height);
			//画边框
			g.setColor(this.getRandomColor(random, 100, 155));
			g.drawRect(0, 0, width-1, height-1);

			//画干扰线
			g.setColor(this.getRandomColor(random, 0, 255));
			g.setStroke(new BasicStroke(1f));
			for (int i = 0; i < this.interferingLineCount; i++) {
				int x = random.nextInt(this.width);
				int y = random.nextInt(this.height);
				int xl = random.nextInt(this.width);
				int yl = random.nextInt(this.height);
				g.drawLine(x, y, x + xl, y + yl);
			}

			//画旋转文字
			int charX = 0;
			List<String> chartList = this.getRandomString(random);
			int charsRealWidth = this.charWidth * this.securityCodeLength;
			if(this.width > charsRealWidth){
				charX = (this.width - charsRealWidth)/2;
			}
			double radianPercent = 0D;
			int chartY = this.height - 5;
			for(String chart : chartList){
				g.setColor(this.getRandomColor(random, 80, 120));
				radianPercent =  Math.PI * (random.nextInt(60)/180D);
				if(random.nextBoolean()) radianPercent = -radianPercent;
				g.rotate(radianPercent, charX + 9, chartY);
				g.drawString(chart, charX, chartY);
				g.rotate(-radianPercent, charX + 9, chartY);
				charX += this.charWidth;
			}

			//释放此图形的上下文以及它使用的所有系统资源
			g.dispose();

			//设置response类型
			response.setContentType("image/jpeg");
			//取消缓存
			response.setHeader("Pragma", "no-cache");
			response.setHeader("Cache-Control", "no-cache");
			response.setDateHeader("Expires", 0);

			//输出图像
			ServletOutputStream os = response.getOutputStream();
			ImageIO.write(buffImg, "jpeg", os);

			os.close();

			//设置Session,将字符串转换成小写
			request.getSession().setAttribute(AppConst.SECURITY_CODE_SESSION_KEY, StringUtils.join(chartList, "").toLowerCase());
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Font registerFont(String fontStr) throws Exception {
		InputStream fontInputStream = SecurityCodeServlet.class.getClassLoader().getResourceAsStream(fontStr);
		Font fontNew = Font.createFont(Font.TRUETYPE_FONT, fontInputStream);
		Font fontNewPt = fontNew.deriveFont(Font.BOLD, this.fontSize);
		fontInputStream.close();

		//注意这里,如果不注册文字的话,什么都画不出来
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		ge.registerFont(fontNew);
		return fontNewPt;
	}

	private List<String> getRandomString(Random random){
		List<String> chartList = new LinkedList<String>();
		for(int i = 0; i < this.securityCodeLength; i++){
			String character = this.chars[random.nextInt(this.chars.length)];
			character = (random.nextBoolean() == true ? character.toUpperCase() : character.toLowerCase());
			chartList.add(character);
		}

		return chartList;
	}

	private Color getRandomColor(Random random, int start, int max){
		int r = start + random.nextInt(max);
		int g = start + random.nextInt(max);
		int b = start + random.nextInt(max);
		return new Color(r, g, b);
	}
}
时间: 2024-08-29 01:40:31

可以旋转文字的验证码的相关文章

C#利用GDI+绘制旋转文字等效果实例

本文实例讲述了C#利用GDI+绘制旋转文字等效果的方法,是非常实用的技巧.分享给大家供大家参考之用.具体如下: C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经过不少的计算过程.利用下面的类可以实现该功能. 具体实现代码如下: using System; using System.Collections.Generic; using System

旋转文字的CSS代码

旋转文字的CSS代码:文字旋转效果如果使用CSS2很难实现,不过CSS3已经提供现成的属性,下面就是一段这样的代码实例和大家分享一下,希望能够给大家带来借鉴作用,代码如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/" /&g

JS实现固定在网页右上角3D风格旋转文字

始终显示在网页右上角的文字特效,而且还可以围绕成3D风格的旋转,文字自己修改下,是使用较原生的JS代码来实现,无jquery和其它插件,代码简单可参考性强. <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>JS实现固定在网页右上角3D风格旋转文字丨石家庄花卉绿植租摆|河北叉车</ti

XE8 FMX Windows 修复列印旋转文字问题

问题:XE8 Firemonkey Windows 无法列印旋转文字(与显示在视窗里的代码相同时) 适用:XE8 Windows 平台(其它平台测试没问题) 修复前效果: 修复后效果: 修复方法: 请将源码 FMX.Printer.Win.pas 复制到自己的工程目录里,再进行修改. 找到 TPrinterWin.GetCanvas 函数,修改如下: uses System.Math.Vectors; // 加入这个 ..... 省略 ...... function TPrinterWin.Ge

PS制作光束散射的旋转文字效果

下面就来介绍一下制作步骤(#^.^#) 1.新建一画布,背景用蓝色渐变.方向根据光束的照射来定. 2.用图形工具的路径画一个圆,然后添加文字.调整其间距和文字大小. 3.栅格化文字,并且复制一层.然后滤镜?模糊?动感模糊,可以重复两次,使其光线颜色加深. 3-1.角度要90度,不然就是横向的了. 3-2.给光线图层添加蒙板,在蒙板上加渐变, 让光线渐隐一下,ctrl+t后按住ctrl+shift+鼠标左键调整光线. 4.接着对文字图层也执行ctrl+t自由变换处理,把文字处理成旋转的效果,并把其

C#利用GDI+绘制旋转文字等效果

C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经过不少的计算过程.利用下面的类可以实现该功能. [csharp] view plaincopy using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D;

跟随鼠标的旋转文字效果

脚本说明: 把如下代码加入<body>区域中 <script language="JavaScript"> <!-- yourLogo='http://www.CsrCode.cn/'; logoFont='Arial'; logoSize=1; // 1-7 only! for larger font sizes alter logoWidth/Height accordingly! logoColor='811188'; logoWidth=70; l

随机生成文字图片验证码

1.随机生成汉字 //传入你要生成汉字的个数 public string GetGB2312String(int count) { var random = new Random(); var bs = new byte[count * 2]; for (var i = 0; i < count; i++) { var c = GetGB2312Char(random); bs[i * 2] = (byte)(c.X + 0xa0); bs[i * 2 + 1] = (byte)(c.Y + 0

python爬虫scrapy框架——人工识别知乎登录知乎倒立文字验证码和数字英文验证码

目前知乎使用了点击图中倒立文字的验证码: 用户需要点击图中倒立的文字才能登录. 这个给爬虫带来了一定难度,但并非无法解决,经过一天的耐心查询,终于可以人工识别验证码并达到登录成功状态,下文将和大家一一道来. 我们学习爬虫首先就要知道浏览器给服务器传输有什么字段(我用的是Safari浏览器进行演示,当然Chrome.Firefox都可以) 我们点击了第一个和第二个文字: 右键审查元素-->点击登录 后可以看到: 从右面可以得到:报文发送的URL是:https://www/zhihu/com/log