简易版servlet(另外的方式其实类似):
package com.tch.excel; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AuthImage extends HttpServlet { private static final long serialVersionUID = 1L; private static char[] codeArr = new char[] {'a','b','c','d','e','f','g','h','i', 'j','k','l','m','n','o','p','q','r', 's','t','u','v','w','x','y','z','A', 'B','C','D','E','F','G','H','I','J', 'K','L','M','N','O','P','Q','R','S', 'T','U','V','W','X','Y','Z','0','1', '2','3','4','5','6','7','8','9'}; private Random random = new Random(); public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int length = codeArr.length; int width = 200; int height = 100; //存放生成的字符 String code = ""; //存放最终的字符组成的字符串验证码 String validateCode = ""; //构建BufferedImage对象,用来存储生成的验证码图片(临时存放在内存中) BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //获取BufferedImage的Graphics对象,Graphics起着画笔的作用,用来写验证码及其它内容 Graphics graphics = bufferedImage.getGraphics(); //开始在BufferedImage对象上面涂背景色 graphics.setColor(Color.white); graphics.fillRect(0, 0, width-1, height-1); //在BufferedImage对象上面画边框 graphics.setColor(Color.black); graphics.drawRect(0, 0, width-1, height-1); //设置要画的字符串的字体 graphics.setFont(new Font("Comic Sans MS",Font.PLAIN,70)); for(int i=0;i<4;i++){ //随机产生字符 code=""+codeArr[random.nextInt(length)]; //随机产生颜色 graphics.setColor(getRandColor()); //将字符写到BufferedImage对象上(Graphics最终是写到对应的BufferedImage对象上面) graphics.drawString(code, 5+i*50, 70); //添加到验证码字符串里面 validateCode += code; } System.out.println("validateCode : "+validateCode); //释放画笔占用的资源 graphics.dispose(); //将生成的图片通过response的输出流返回给页面 ImageIO.write(bufferedImage, "JPEG", response.getOutputStream()); } //产生随机颜色 private Color getRandColor() { Random random = new Random(); Color color[] = new Color[10]; color[0] = new Color(32, 158, 25); color[1] = new Color(218, 42, 19); color[2] = new Color(31, 75, 208); return new Color(random.nextInt(220), random.nextInt(220), random.nextInt(220)); } }
servlet:
package com.tch.excel; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AuthImage extends HttpServlet { private static final long serialVersionUID = 1L; private Font mFont = new Font("Arial Black", Font.PLAIN, 16); public void init() throws ServletException { super.init(); } Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int width = 60, height = 18; mFont = new Font("Times New Roman", Font.PLAIN, 23); // 阻止生成的页面内容被缓存,保证每次重新生成随机验证码 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 生成随机类 Random random = new Random(); // 设定背景色 g.setColor(getRandColor(200, 250)); g.fillRect(1, 1, width - 1, height - 1); // 设定字体 // g.setFont(new Font("Times New Roman",Font.PLAIN,18)); // 画边框 g.setColor(new Color(102, 102, 102)); g.drawRect(0, 0, width - 1, height - 1); g.setFont(mFont); // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到 g.setColor(getRandColor(160, 200)); for (int i = 0; i < 200; i++) { int x = random.nextInt(width - 1); int y = random.nextInt(height - 1); int xl = random.nextInt(6) + 1; int yl = random.nextInt(12) + 1; g.drawLine(x, y, x + xl, y + yl); } for (int i = 0; i < 70; i++) { int x = random.nextInt(width - 1); int y = random.nextInt(height - 1); int xl = random.nextInt(12) + 1; int yl = random.nextInt(6) + 1; g.drawLine(x, y, x - xl, y - yl); } String sRand = ""; for (int i = 0; i < 4; i++)// 4位验证码 { String tmp = getRandomChar(); // 将产生的四个随机数组合在一起 sRand += tmp; // 用随机产生的颜色将验证码绘制到图像中 g.setColor(new Color(20 + random.nextInt(110), 20 + random .nextInt(110), 20 + random.nextInt(110))); g.drawString(tmp, 12 * i + 5, 15); } g.dispose(); request.getSession().setAttribute("validateCode", sRand); System.out.println("validateCode : "+sRand); // 将图像输出到Servlet输出流中 OutputStream outputStream = response.getOutputStream(); ImageIO.write(image, "JPEG", outputStream); outputStream.close(); } private String getRandomChar() { int rand = (int) Math.round(Math.random() * 2); long itmp = 0; char ctmp = '\u0000'; switch (rand) { case 1: itmp = Math.round(Math.random() * 25 + 65); ctmp = (char) itmp; return String.valueOf(ctmp); case 2: itmp = Math.round(Math.random() * 25 + 97); ctmp = (char) itmp; return String.valueOf(ctmp); default: itmp = Math.round(Math.random() * 9); return String.valueOf(itmp); } } }
在页面中:
<a href="###"><img src="http://localhost:8080/xxx/servlet/authImage" width="180" height="40" onclick="refreshCode();"></a> <script type="text/javascript" charset="utf-8"> function refreshCode(obj){ obj.src = 'http://localhost:8080/xxx/servlet/authImage?d='+(new Date().getTime()); } </script>
并且在web.xml中配置authImage这个servlet即可;
其中生成验证码的过程还可以用另外的方法:
SessionHelper.setValidCode(req, AuthImageYj.SIMPLE_CAPCHA_SESSION_KEY, test); /** * 得到输出流 */ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(resp .getOutputStream()); BufferedImage bi = new BufferedImage(ImageWidth + 10, ImageHeight, BufferedImage.TYPE_BYTE_INDEXED); Graphics2D graphics = bi.createGraphics(); /** * 设置背景色 */ // graphics.setColor(Color.white); graphics.setColor(new Color(random.nextInt(100), random.nextInt(100), random.nextInt(200))); graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight()); graphics.setColor(Color.black); AttributedString attstr = new AttributedString(test); TextLayout textTl = new TextLayout(test, new Font("Courier", Font.BOLD, 70), new FontRenderContext(null, true, false)); AffineTransform textAt = graphics.getTransform(); graphics.setFont(new Font("Courier", Font.BOLD, 70)); graphics.setColor(this.getRandColor()); graphics.drawString(test, 10, 70); // textTl.draw(graphics, 4, 60); int w = bi.getWidth(); int h = bi.getHeight(); shear(graphics, w, h, Color.white); // this.drawThickLine(graphics, 0, generator.nextInt(ImageHeight) + 1, // ImageWidth, generator.nextInt(ImageHeight) + 1, 4, Color.BLACK); resp.setContentType("image/jpg"); encoder.encode(bi);
通过struts2:可以参考http://blog.csdn.net/Yao_Qinwei/article/details/8244115
(蛋疼,过程中struts.xml没有加 <param name="inputName">imageStream</param>
然后再action中使用 InputStream inputName,不知道为什么一直不行,非要换个名字才行,很蛋疼,不住地为啥)
将生成验证码的代码,放到action类里面: import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Map; import java.util.Random; import org.apache.struts2.interceptor.SessionAware; import sun.awt.image.ImageFormatException; import com.opensymphony.xwork2.ActionSupport; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; public class SecurityCodeImageAction extends ActionSupport implements SessionAware { private static char[] captchars = new char[] { 'a', 'b', 'c', 'd', 'e', '2', '3', '4', '5', '6', '7', '8', 'g', 'f', 'y', 'n', 'm', 'n', 'p', 'w', 'x' }; private Random generator = new Random(); // 图片流 private ByteArrayInputStream imageStream; private ByteArrayInputStream inputName; // session域 private Map<String, Object> session; private void drawThickLine(Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c) { // The thick line is in fact a filled polygon g.setColor(c); int dX = x2 - x1; int dY = y2 - y1; // line length double lineLength = Math.sqrt(dX * dX + dY * dY); double scale = (double) (thickness) / (2 * lineLength); // The x and y increments from an endpoint needed to create a // rectangle... double ddx = -scale * (double) dY; double ddy = scale * (double) dX; ddx += (ddx > 0) ? 0.5 : -0.5; ddy += (ddy > 0) ? 0.5 : -0.5; int dx = (int) ddx; int dy = (int) ddy; // Now we can compute the corner points... int xPoints[] = new int[4]; int yPoints[] = new int[4]; xPoints[0] = x1 + dx; yPoints[0] = y1 + dy; xPoints[1] = x1 - dx; yPoints[1] = y1 - dy; xPoints[2] = x2 - dx; yPoints[2] = y2 - dy; xPoints[3] = x2 + dx; yPoints[3] = y2 + dy; g.fillPolygon(xPoints, yPoints, 4); } /** * @throws IOException * @throws ImageFormatException * @see javax.servlet.http.HttpServlet#void * (javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ public String execute() { int ImageWidth = 200; int ImageHeight = 100; Random random = new Random(); int car = captchars.length - 1; /** * 产生随机字符串 */ String test = ""; for (int i = 0; i < 4; i++) { test += captchars[generator.nextInt(car) + 1]; } System.out.println(test); /** * 放放Session */ /** * 得到输出流 */ JPEGImageEncoder encoder = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); encoder = JPEGCodec.createJPEGEncoder(bos); BufferedImage bi = new BufferedImage(ImageWidth + 10, ImageHeight, BufferedImage.TYPE_BYTE_INDEXED); Graphics2D graphics = bi.createGraphics(); /** * 设置背景色 */ // graphics.setColor(Color.white); graphics.setColor(new Color(random.nextInt(100), random.nextInt(100), random.nextInt(200))); graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight()); graphics.setColor(Color.black); // AttributedString attstr = new AttributedString(test); // // TextLayout textTl = new TextLayout(test, new Font("Courier", // Font.BOLD, // 70), new FontRenderContext(null, true, false)); // AffineTransform textAt = graphics.getTransform(); graphics.setFont(new Font("Courier", Font.BOLD, 70)); graphics.setColor(this.getRandColor()); graphics.drawString(test, 10, 70); // textTl.draw(graphics, 4, 60); int w = bi.getWidth(); int h = bi.getHeight(); shear(graphics, w, h, Color.white); try { encoder.encode(bi); } catch (IOException e) { e.printStackTrace(); } inputName = new ByteArrayInputStream(bos.toByteArray()); return "success"; } /** * 产生随机字体 * * @return */ private Font getFont() { Random random = new Random(); Font font[] = new Font[5]; font[0] = new Font("Ravie", Font.PLAIN, 45); font[1] = new Font("Antique Olive Compact", Font.PLAIN, 45); font[2] = new Font("Forte", Font.PLAIN, 45); font[3] = new Font("Wide Latin", Font.PLAIN, 40); font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, 45); return font[random.nextInt(5)]; } public ByteArrayInputStream getImageStream() { return imageStream; } public ByteArrayInputStream getInputName() { return inputName; } /** * 随机产生定义的颜色 * * @return */ private Color getRandColor() { Random random = new Random(); Color color[] = new Color[10]; color[0] = new Color(32, 158, 25); color[1] = new Color(218, 42, 19); color[2] = new Color(31, 75, 208); // return color[random.nextInt(3)]; return new Color(random.nextInt(220), random.nextInt(220), random.nextInt(220)); } public void setImageStream(ByteArrayInputStream imageStream) { this.imageStream = imageStream; } public void setInputName(ByteArrayInputStream inputName) { this.inputName = inputName; } public void setSession(Map<String, Object> session) { this.session = session; } private void shear(Graphics g, int w1, int h1, Color color) { shearX(g, w1, h1, color); shearY(g, w1, h1, color); } public void shearX(Graphics g, int w1, int h1, Color color) { int period = generator.nextInt(2); boolean borderGap = true; int frames = 1; int phase = generator.nextInt(2); for (int i = 0; i < h1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(0, i, w1, 1, (int) d, 0); if (borderGap) { g.setColor(color); g.drawLine((int) d, i, 0, i); g.drawLine((int) d + w1, i, w1, i); } } } public void shearY(Graphics g, int w1, int h1, Color color) { int period = generator.nextInt(40) + 10; // 50; boolean borderGap = true; int frames = 20; int phase = 7; for (int i = 0; i < w1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(i, 0, 1, h1, 0, (int) d); if (borderGap) { g.setColor(color); g.drawLine(i, (int) d, i, 0); g.drawLine(i, (int) d + h1, i, h1); } } } }
struts.xml代码加入:
<action name="SecurityCodeImageAction" class="SecurityCodeImageAction"> <result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">imageStream</param> <param name="bufferSize">2048</param> </result> </action>
页面:
<html> <head> <script type="text/javascript"> function cl2(a) { a.src = 'http://localhost:8090/WebTest/SecurityCodeImageAction.action?t="' + new Date() } </script> </head> <body> <s:a href="download.action">下载</s:a> <a href="###"><image src="/Struts2_10/SecurityCodeImageAction.action" width="180" height="40" onclick="cl2(this);"></image> </a> </body> </html>
OK。
相关推荐
### Struts2 生成验证码知识点解析 #### 一、引言 在Web应用程序开发中,验证码是一种常见的安全机制,用于防止自动化的恶意攻击,如垃圾邮件发送或非法登录尝试等。Struts2作为一款流行的Java Web应用框架,支持...
在Struts2中,我们可以创建一个Action来生成验证码,这个Action可以包含一个方法,该方法生成验证码并将其保存到session。Struts2配置文件(struts.xml)中会定义这个Action,并指定其处理的请求路径。 在视图层,...
6. **Servlet**:这个项目中可能包含一个专门生成验证码的Servlet。它会随机生成一串中文字符,存储在Session中,并将其绘制到图像上。生成的图像以JPEG或PNG格式输出,供JSP页面显示。 7. **中文字符库**:为了...
例如,验证码可能通过Servlet生成并存储在Session中,然后在JSP页面上显示给用户。 总的来说,这个实例提供了从用户界面到后台服务的完整登录流程,涵盖了Struts2和Spring3的核心功能。通过学习和实践这个实例,...
在实际应用中,你可能需要将这个Servlet集成到Spring Boot、Struts2或其他Java Web框架中,以适应项目的需求。同时,验证码的安全性也是一个重要的考虑因素,例如,可以考虑增加更复杂的字符集、增加字符数量、使用...
3. **响应HTTP请求**:当用户请求验证码时,Servlet接收到请求后,生成验证码并绘制图像,然后将其编码为Base64字符串,通过HTTP响应发送到客户端。客户端可以通过JavaScript动态创建img标签,设置src属性为这个Base...
在Struts2配置文件(struts.xml)中,我们需要为生成验证码的Action添加一个对应的URL映射,以及一个显示验证码的JSP页面。JSP页面可能包含一个img标签,其src属性指向生成验证码的Action URL。当用户点击刷新按钮...
在IT行业中,生成验证码图片和使用Struts框架进行文件下载是常见的功能需求,尤其是在网站的安全性和用户体验方面。这篇博文“生成验证码图片,并使用Struts download下载”将介绍这两个主题。 首先,我们来看...
彩色验证码的实现是在生成验证码的基础上增加了颜色元素,使得验证码更难以被自动化工具识别,增强了安全性。 JSP是一种基于Java的服务器端脚本语言,用于创建动态网页。在本项目中,`code.jsp`是核心页面,它负责...
在Struts2应用中,通常会将这个Servlet配置为一个Action,当用户请求验证码时,通过Action调用`service`方法生成验证码并显示。在用户提交表单时,服务器会检查用户输入的验证码是否与生成的验证码匹配,以此来确认...
Servlet接收到请求后,生成验证码,将其保存到session,并返回一个包含验证码图像的HTTP响应。这个响应的Content-Type应设置为"image/jpeg"或"image/png",以便浏览器能正确解析。验证码图像通常通过绘制文本、线条...
生成验证码,本验证码为Servlet形式,可以凭开发经验,例如在Struts中,将其写在Action的方法中(void类型)从而转为Struts形式,调用时只需使img标签的src属性= 1.(servletname) 2.(methodname_actionname.action)
生成验证码的Action可能会返回一个"success"结果,对应的视图可能是直接输出验证码图像的流。 4. **视图渲染**: 类似于Servlet,验证码Action生成的图像也会通过HTTP响应返回给客户端,但此时是通过Struts2的...
验证码在IT领域,尤其...通过Servlet或Struts2,我们可以构建出高效且安全的验证码系统,保护我们的Web应用免受自动化攻击。开发者在实际项目中可以根据需求选择合适的方式,结合提供的文档和代码样例进行实践和优化。
在Struts2框架中,我们可以创建一个Action,该Action调用Servlet生成验证码并返回图片。为了实现这个功能,我们需要在struts.xml配置文件中添加一个映射,将特定的请求路径指向生成验证码的Servlet。 3. **SSH2...
例如,创建一个专门处理验证码请求的Servlet,其中包含生成验证码的doGet方法和验证验证码的doPost方法。此外,还可以使用jCaptcha提供的JSP标签库来简化视图层的集成。 总之,jCaptcha作为一款强大的Java验证码库...
8. **Plug-in机制**:Struts2支持插件化开发,如描述中提及的"插件包",开发者可以通过编写插件扩展Struts2的功能,比如国际化、验证码、上传下载等。 9. **Struts2的jar包**:压缩包中的jar文件可能包括Struts2的...
可以使用第三方库如Servlet Filter或Struts2插件来生成和验证随机的验证码图片。在Action中,需要检查用户提交的验证码是否与服务器生成的验证码一致。 错误提示是用户体验的重要组成部分。Struts2提供了一套异常...
在这个Java实现验证码的详细步骤中,我们将探讨如何在Servlet中生成验证码,将其发送到前端,并整合到Struts框架中。下面,我们将逐步深入这个过程。 首先,验证码的生成通常涉及到以下几个核心组件: 1. **随机数...
这在很多场景下都是有用的,比如生成验证码、个性化定制图片或者数据可视化等。 首先,我们要明白在线生成图像的核心技术是基于服务器端的图形库,如Java的Graphics2D API或第三方库如Apache Batik。在Struts框架中...