表单重复提交

思想:通过验证码的形式防止表单重复提交。

通过JavaEE实现:

思路:

1,写一个表单,比如是用户注册表单,在表单中定义一个img标签,将src指定为一个servlet,这个servlet将动态生成一个验证码图片,也就是每次请求这个页面的时候都会生成一个新的验证码。

2,Servlet生成验证码,在这个servlet生成验证码之后,要将这个验证码的值存放在session中,用户放置重复提交,用到的token机制(令牌机制)。Servlet生成验证码的代码如下:

 

public class VerifyCodeServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//产生验证码。
		//首先准备一些数据。
		String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
		//准备随机函数,从这些数据中随机取值,
		Random random = new Random();
		int width = 60;
		int height = 30;
		//创建图像。
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		//创建画板。
		Graphics g = image.getGraphics();
		//设置画笔颜色。
		g.setColor(Color.BLACK);
		//填充矩形。
		g.fillRect(0, 0, width, height);
		g.setColor(Color.WHITE);
		g.fillRect(1, 1, width-2, height-2);
		
		//设置字体。
		g.setFont(new Font("宋体",Font.BOLD,20));
		//创建一个StringBuilder来构建随机生成 的四位验证码
		StringBuilder sb = new StringBuilder();
		//用循环获取4为随机码。
		for(int i=0;i<4;i++) {
			//设置随机颜色。
			g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
			//获得随机字符。
			int index = random.nextInt(data.length());
			String str = data.substring(index, index+1);
			//添加到缓冲的sb中。
			sb.append(str);
			//绘制到画板中。
			g.drawString(str,width/6*(i+1),20);
		}
		//将数据缓存到session,以便于在检查的servlet中进行验证码的比对。
		String bufferData = sb.toString();
		request.getSession().setAttribute("sessionVerifyCodeData", bufferData);
		//添加干扰点,线
		for(int i=0;i<5;i++) {
			g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
			g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
		}
		//将服务器内存中的数据发送到浏览器。
		ImageIO.write(image,"jpg",response.getOutputStream());
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);

	}

}

3,用户填好验证码表单,提交到servlet,servlet先获取到用户提交的验证码,再获取服务器的验证码。首先判断服务器获取的验证码是否为空,如果是null,则提示用户“重复提交”,让用户重新刷新页面,重新提交。如果服务器有数据,则先将服务器的session中的数据删除,保证用户重复提交的时候服务器的session中已经没有数据,删除之后再判断session中的数据是否与用户提交的数据一致,一致则注册成功,不一致则返回信息提示用户验证码错误。

//判断验证码----------------------------------------------------------------------
		//获取用户填写的验证码
		String verifyCode = request.getParameter("verifyCode");
		//获取session中的验证码,如果二者一致,则填写正确。
		String sessionVerifyCodeData = (String)request.getSession().getAttribute("sessionVerifyCodeData");
		//首先判断服务器是否有session中的验证码数据。
		if(sessionVerifyCodeData!=null) {
			//有数据。将session中缓存的数据移除,保证验证码的一次性,
			request.getSession().removeAttribute("sessionVerifyCodeData");
			if(!sessionVerifyCodeData.equalsIgnoreCase(verifyCode)) {
				//如果不匹配
				request.setAttribute("message", "验证码有误,请重新填写");
				request.getRequestDispatcher("/client/register.jsp").forward(request, response);
				return;
			} 
		} else {
			//重复提交
			request.setAttribute("message", "不要重复提交");
			request.getRequestDispatcher("/client/register.jsp").forward(request, response);
			return;
		}

4,验证。

Struts2实现:

核心步骤:

(1)  在jsp页面写一个<s:token /> 标签。

(2)  在struts.xml中配置信息。配置拦截器,在当前的action中,加入defaultStack默认拦截器,在添加一个拦截器引用,引用token拦截器,使token拦截器追加到默认拦截器后面。在token中配置参数,参数名为includeMethods,用户说明这个token用于当前action类的那个方法,我们默认在注册方法register中。

(3)  设定错误处理信息,result接收的是invalid.token,再配置国际化文件,在当前Action所在目录中写一个properties文件,根据返回的英文信息,去default.properties中查询相应的键,在自定义的properties中将这个键用自己的信息覆盖即可。

实现原理:

基本与JavaEE的方式相同,首先,在jsp中定义一个<s:token />标签,当浏览器访问这个jsp时,<s:token />标签会自动生成一个随机数据,保存到服务器的session中,并在当前jsp中的一个隐藏域中记录这个随机生成的数据,当用户提交表单时,会将隐藏域中的数据带到服务器,服务器获取用户提交的信息,即这个随机码,再从服务器的session中获取数据。先判断服务器获取的数据是否是空,如果是空,则表明用户重复提交了数据,返回错误信息。如果不是空,则用户时第一次提交,先将服务器的session中的数据删除,以便于用户重复提交的时候session中的数据为空,再判断用户提交的数据与服务器获取的数据是否相等,如果相等,则注册成功,如果不相等,则回显“验证码输入错误”。


你可能感兴趣的:(javaee)