您的位置:首页 > 其它

实现图片验证码,其实就是简单的验证码实现,记录一下

2014-08-06 14:03 645 查看
今天一个小网站被黑了,本来就是一个临时做了一两天的小网站,因为不需要登陆,所以只是在后台加入了一个ip过滤,没想那么复杂。但是持续被黑,经过将近一个上午的修改,终于暂时避免被黑。

1、首先昨天被黑,想到的是ip过滤机制出现了问题,查看数据库,果然发现ip不对劲,它是一个真实ip加上了一个随机生成的数字,我看可能是他模拟了ip,把这个真实ip过滤掉了。相安无事。

2、今天上午又被黑了,发现他可以模拟ip,没有规律可查,所以想到了使用验证码,首先是生成一个随机数存放在cookie中,1分钟后又被黑掉。

3、把随机验证码存放在session中,2分钟后被黑掉。

4、把随机验证生成图片,然后数字存放在session中。2分钟后又被黑掉了。

5、查看后台日志,发现程序本身是存在bug的,因为黑网站的人并不是通过浏览器访问,而是通过程序实现的,所以程序修改了下。暂时没有被黑了。

下面是我实现的,漏洞肯定还是有的。只是我不知道罢了。

一个验证码生成器:

public class Scaptcha {

// 图片的宽度。

private int width = 120;

// 图片的高度。

private int height = 40;

// 验证码字符个数

private int codeCount = 4;

// 验证码干扰线数

private int lineCount = 50;

// 验证码

private String code = null;

// 验证码图片Buffer

private BufferedImage buffImg = null;

private char[] codeSequence = { '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' };

// 生成随机数

private Random random = new Random();

public Scaptcha() {

this.createCode();

}

/**

*

* @param width

* 图片宽

* @param height

* 图片高

*/

public Scaptcha(int width, int height) {

this.width = width;

this.height = height;

this.createCode();

}

/**

*

* @param width

* 图片宽

* @param height

* 图片高

* @param codeCount

* 字符个数

* @param lineCount

* 干扰线条数

*/

public Scaptcha(int width, int height, int codeCount, int lineCount) {

this.width = width;

this.height = height;

this.codeCount = codeCount;

this.lineCount = lineCount;

this.createCode();

}

public void createCode() {

int codeX = 0;

int fontHeight = 0;

fontHeight = height - 5;// 字体的高度

codeX = width / (codeCount+3);// 每个字符的宽度

// 图像buffer

buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

Graphics2D g = buffImg.createGraphics();

// 将图像填充为白色

g.setColor(Color.WHITE);

g.fillRect(0, 0, width, height);

// 创建字体

ImgFontByte imgFont = new ImgFontByte();

Font font = imgFont.getFont(fontHeight);

g.setFont(font);

// 绘制干扰线

for (int i = 0; i < lineCount; i++) {

int xs = getRandomNumber(width);

int ys = getRandomNumber(height);

int xe = xs + getRandomNumber(width / 8);

int ye = ys + getRandomNumber(height / 8);

g.setColor(getRandomColor());

g.drawLine(xs, ys, xe, ye);

}

StringBuffer randomCode = new StringBuffer();

// 随机产生验证码字符

for (int i = 0; i < codeCount; i++) {

String strRand = String.valueOf(codeSequence[random

.nextInt(codeSequence.length)]);

// 设置字体颜色

g.setColor(getRandomColor());

// 设置字体位置

g.drawString(strRand, (i + 1) * codeX,

getRandomNumber(height / 2) + 25);

randomCode.append(strRand);

}

code = randomCode.toString();

}

/** 获取随机颜色 */

private Color getRandomColor() {

int r = getRandomNumber(255);

int g = getRandomNumber(255);

int b = getRandomNumber(255);

return new Color(r, g, b);

}

/** 获取随机数 */

private int getRandomNumber(int number) {

return random.nextInt(number);

}

public void write(String path) throws IOException {

OutputStream sos = new FileOutputStream(path);

this.write(sos);

}

public void write(OutputStream sos) throws IOException {

ImageIO.write(buffImg, "png", sos);

sos.close();

}

public BufferedImage getBuffImg() {

return buffImg;

}

public String getCode() {

return code;

}

/** 字体样式类 */

class ImgFontByte {

public Font getFont(int fontHeight) {

try {

Font baseFont = Font.createFont(Font.TRUETYPE_FONT,

new ByteArrayInputStream(hex2byte(getFontByteStr())));

return baseFont.deriveFont(Font.PLAIN, fontHeight);

} catch (Exception e) {

return new Font("Arial", Font.PLAIN, fontHeight);

}

}

private byte[] hex2byte(String str) {

if (str == null)

return null;

str = str.trim();

int len = str.length();

if (len == 0 || len % 2 == 1)

return null;

byte[] b = new byte[len / 2];

try {

for (int i = 0; i < str.length(); i += 2) {

b[i / 2] = (byte) Integer.decode(

"0x" + str.substring(i, i + 2)).intValue();

}

return b;

} catch (Exception e) {

return null;

}

}

// 字体文件的十六进制字符串

private String getFontByteStr() {

return "字段很长,就不放进来了";

}

}

}

然后是生成验证码的servlet

public synchronized void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setCharacterEncoding("UTF-8");

ArticleDao articleDao = new ArticleDao();

// 组装图片的路径

Scaptcha instance = new Scaptcha();

/*Cookie cookie = new Cookie("scaptcha", instance.getCode());

cookie.setMaxAge(1800);

response.addCookie(cookie);

String code=instance.getCode();*/

String code=instance.getCode();

request.getSession().setAttribute("scaptcha", code);

System.out.println(code);

String temp=request.getRealPath("/upload");

instance.write(temp+"//ss.jpg");

final String bitmapUrl = "upload/upload/";

List<Article> articles= articleDao.findArticleAll();

for(int i = 0 ; i<articles.size() ; i++){

String bitmap = bitmapUrl+articles.get(i).getPhotoUrl();

articles.get(i).setPhotoUrl(bitmap);

// System.out.println("图片路径 "+bitmap);

}

request.setAttribute("articles", articles);

request.getRequestDispatcher("/jsp/many_vote.jsp").forward(request, response);

}

最后是验证的servlet

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setCharacterEncoding("UTF-8");

PrintWriter out = response.getWriter();

ArticleDao articleDao = new ArticleDao();

// 多个投票的id

String[] many_vote = request.getParameterValues("article_vote");

String scaptcha=request.getParameter("scaptcha").toUpperCase();

String scaptchaC="";

String code=(String) request.getSession().getAttribute("scaptcha");

if(code==null){

scaptchaC="";

}else{

scaptchaC=code;

}

// 获取ip

// String ip = request.getRemoteAddr();

// String ip = InetAddress.getLocalHost().getHostAddress();

String ip = request.getHeader("x-forwarded-for");

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("WL-Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getRemoteAddr();

}

if(scaptcha.equals("")||scaptcha==null){

System.out.println("scaptcha是空的");

out.print("<script type='text/javascript'>alert('请输入验证码...!');location.href='"

+ request.getContextPath() + "/index.jsp';</script>");

}else{

if(!scaptcha.equals(scaptchaC)){

out.print("<script type='text/javascript'>alert('该验证码不匹配...!');location.href='"

+ request.getContextPath() + "/index.jsp';</script>");

}

if (many_vote != null && many_vote.length == 20) {

//判断ip是否为空

if(ip!=null && !ip.equals("") && !ip.contains(",") && interapt(ip)){

// 判断ip是否重复

if (articleDao.isIpRepetition(ip)) {

out.print("<script type='text/javascript'>alert('此ip已经参加投票...!');location.href='"

+ request.getContextPath() + "/index.jsp';</script>");

} else {

// 循环插入

for (int i = 0; i < many_vote.length; i++) {

articleDao.voteAdd(ip, many_vote[i]);

}

out.print("<script type='text/javascript'>alert('投票成功...!');location.href='"

+ request.getContextPath() + "/index.jsp';</script>");

}

}else{

out.print("<script type='text/javascript'>alert('系统繁忙,请稍后投票...!');location.href='"

+ request.getContextPath() + "/index.jsp';</script>");

}

} else {

// out.print("<script type='text/javascript'>alert('请检查投票数是否达到20人...!');location.href='"

// + request.getContextPath() + "/index.jsp';</script>");

out.print("<script type='text/javascript'>alert('请检查投票数是否达到20人...!');window.history.back(-1);</script>");

}

}

System.out.println(scaptchaC+"####"+scaptcha);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐