【Struts实现页面验证码】

本文详细介绍了如何使用Java实现安全验证码的生成流程,包括获取随机字符串、生成带噪点的图片以及创建Action来展示验证码。通过步骤指导,帮助开发者轻松掌握安全验证码的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一步,获取随机的字符串:

public class SecurityCode {

	public enum SecurityCodeLevel {
		Simple, Medium, Hard
	};
	
	//对外提供被调用的方法,返回一个随机串
	public static String getSecurityCode() {
		return getSecurityCode(4, SecurityCodeLevel.Medium, false);
	}

	public static String getSecurityCode(int length, SecurityCodeLevel level,
			boolean isCanRepeat) {
		// 随机抽取len个字符
		int len = length;
		// 字符集合(除去易混淆的数字0、数字1、字母l、字母o、字母O)
		char[] codes = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
				'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', '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', 'L', 'M', 'N',
				'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
		// 根据不同的难度截取字符数组
		if (level == SecurityCodeLevel.Simple) {
			codes = Arrays.copyOfRange(codes, 0, 9);
		} else if (level == SecurityCodeLevel.Medium) {
			codes = Arrays.copyOfRange(codes, 0, 33);
		}
		// 字符集合长度
		int n = codes.length;
		// 抛出运行时异常
		if (len > n && isCanRepeat == false) {
			throw new RuntimeException(
					String.format(
							"调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常,当isCanRepeat为%3$s时,传入参数%1$s不能大于%4$s",
							len, level, isCanRepeat, n));
		}

		// 存放抽取出来的字符
		char[] result = new char[len];

		// 判断能否出现重复的字符
		if (isCanRepeat) {
			for (int i = 0; i < result.length; i++) {
				// 索引 0 and n-1
				int r = (int) (Math.random() * n);

				// 将result中的第i个元素设置为codes[r]存放的数值
				result[i] = codes[r];
			}
		} else {
			for (int i = 0; i < result.length; i++) {
				// 索引 0 and n-1
				int r = (int) (Math.random() * n);

				// 将result中的第i个元素设置为codes[r]存放的数值
				result[i] = codes[r];

				// 必须确保不会再次抽取到那个字符,因为所有抽取的字符必须不相同。
				// 因此,这里用数组中的最后一个字符改写codes[r],并将n减1
				codes[r] = codes[n - 1];
				n--;
			}
		}
		return String.valueOf(result);
	}

}



第二步,获得一张带有噪点的图片,图片的宽度和高度可以自己调:

public class SecurityImage {
	
	public static BufferedImage createImage(String securityCode) {
		 
	       // 验证码长度
	       int codeLength = securityCode.length();
	       // 字体大小
	       int fSize = 18;
	       int fWidth = fSize + 1;
	       // 图片宽度
	       int width = codeLength * fWidth + 20;
	       // 图片高度
	       int height = fSize * 2 + 10;
	       
	       System.out.println("width=" + width +" height=" + height);
	       // 图片
	       BufferedImage image = new BufferedImage(width, height,
	              BufferedImage.TYPE_INT_RGB);
	       Graphics g = image.createGraphics();
	 
	       // 设置背景色
	       g.setColor(Color.WHITE);
	       // 填充背景
	       g.fillRect(0, 0, width, height);
	 
	       // 设置边框颜色
	       g.setColor(Color.DARK_GRAY);
	       // 边框字体样式
	       g.setFont(new Font("Arial", Font.BOLD, height - 2));
	       // 绘制边框
	       g.drawRect(0, 0, width - 1, height - 1);
	 
	       // 绘制噪点
	       Random rand = new Random();
	       // 设置噪点颜色
	       g.setColor(Color.LIGHT_GRAY);
	       for (int i = 0; i < codeLength * 6; i++) {
	           int x = rand.nextInt(width);
	           int y = rand.nextInt(height);
	           // 绘制1*1大小的矩形
	           g.drawRect(x, y, 1, 1);
	       }
	 
	       // 绘制验证码
	       int codeY = 2* height / 3;
	       // 设置字体颜色和样式
	       g.setColor(new Color(0, 0, 153));
	       g.setFont(new Font("Georgia", Font.BOLD, fSize));
	       for (int i = 0; i < codeLength; i++) {
//	           g.drawString(String.valueOf(securityCode.charAt(i)), i * 16 + 10,
//	                  codeY);
	           g.drawString(String.valueOf(securityCode.charAt(i)), i*20+10,
	        		   codeY);
	       }
	       // 关闭资源
	       g.dispose();
	 
	       return image;
	    }
	 
	   	//将图片转换成字节流并返回
	    public static ByteArrayInputStream getImageAsInputStream(String securityCode) {
	 
	       BufferedImage image = createImage(securityCode);
	       return convertImageToStream(image);
	    }
	 
	   
	    private static ByteArrayInputStream convertImageToStream(BufferedImage image) {
	 
	       ByteArrayInputStream inputStream = null;
	       ByteArrayOutputStream bos = new ByteArrayOutputStream();
	       JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(bos);
	       try {
	           jpeg.encode(image);
	           byte[] bts = bos.toByteArray();
	           inputStream = new ByteArrayInputStream(bts);
	       } catch (ImageFormatException e) {
	           e.printStackTrace();
	       } catch (IOException e) {
	           e.printStackTrace();
	       }
	       return inputStream;
	    }

}



第三步,创建一个Action,设置一个字节输入流的属性,写好set/get方法,让Struts框架自动注入。

public class ValidCodeAction extends ActionSupport {

	private static final long serialVersionUID = 5633780176793520460L;
	// 图片流
	private ByteArrayInputStream imageStream;

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		try {
			HttpServletRequest request = ServletActionContext.getRequest();
			String securityCode = SecurityCode.getSecurityCode();
			imageStream = SecurityImage.getImageAsInputStream(securityCode);
			// 放入session中
			// session.put("securityCode", securityCode);
			System.out.println("securityCode = " + securityCode);
			request.getSession().setAttribute("securityCode", securityCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return SUCCESS;
	}

	public ByteArrayInputStream getImageStream() {
		return imageStream;
	}

	public void setImageStream(ByteArrayInputStream imageStream) {
		this.imageStream = imageStream;
	}

}

第四步,在struts.xml配置文件当中配置上面的Action。
	<package name="utils" namespace="/" extends="struts-default">
		<action name="SecurityCodeImageAction" class="com.bear.utils.ValidCodeAction">
			<result name="success" type="stream">
				<param name="contentType">image/jpeg</param>
				<param name="inputName">imageStream</param>
				<param name="bufferSize">2048</param>
			</result>
		</action>
	</package>


第五步,来到jsp展示页面,在需要的地方加上以下img标签:

<img src="<%=path%>/SecurityCodeImageAction.action"
									alt="验证码" name="checkImg" id="checkImg"
									style="position:relative; left:20px; height: 100%;display: inline-block; vertical-align: middle;"
									onClick="document.getElementById('checkImg').src='<%=path%>/SecurityCodeImageAction.action?timestamp='+ (new Date().getTime().toString(36)); return false" />


以上步骤做完后,就可以验证效果了。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值