• 使用令牌实现防重复提交


    重复提交的情景:

      一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,由于更新、删除一般都是通过id来操作(例如: updateXXXById, removeXXXById),所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。

    1.常见防重提交的方式主要有:js方式 验证码  令牌

    2.这里主要介绍第三种:

    其实从原理上来说,第二种跟第三种是一样的。都是通过生成随机数,存放于session,使得重复提交时获取到的数据与上一次发的数据不一致,从而不满足提交条件。

    分三步:

    1.初始化令牌值 AvoidSubmitFormAgain.initTokenProcessor(request, response); 生成token,并放置到session里

    2.在页面上获取刚才生成的令牌值token

    3.在后台对token进行校验:AvoidSubmitFormAgain.isTokenValid(request)  true:可以提交  false:重复提交

    4.清除当前的令牌值:AvoidSubmitFormAgain.removeTokenProecessor(request);

    下面是具体代码:

    令牌生成器:TokenProcessor.java

    package com.sie.commons;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Random;
    
    import sun.misc.BASE64Encoder;
    
    public class TokenProcessor {
    	/*
    	 * 1.把构造函数私有
    	 * 2.自己创建一个
    	 * 3.对外暴露一个方法,允许获取上面创建的对象
    	 * */
    	private static final TokenProcessor instance=new TokenProcessor();
    	private TokenProcessor(){}
    	public static TokenProcessor getInstance()
    	{
    		return instance;
    	}
    	public String generateToken()
    	{
    		String token=System.currentTimeMillis()+new Random().nextInt()+"";
    		try {
    			MessageDigest md=MessageDigest.getInstance("md5");
    			byte[] md5=md.digest(token.getBytes());
    			//base64编码
    			BASE64Encoder encoder=new BASE64Encoder();
    			
    			return encoder.encode(md5);
    		} catch (NoSuchAlgorithmException e) {
    			// TODO Auto-generated catch block
    			throw new RuntimeException(e);
    		}
    	}
    	
    }
    

    第二个是我自己整合后一个令牌的操作工具AvoidSubmitFormAgain.java

    package com.sie.commons;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 重复提交工具类
     * @author lyq
     *
     */
    public class AvoidSubmitFormAgain {
    	/**
    	 * 初始化token
    	 * @param request
    	 * @param response
    	 * @param path
    	 * @throws ServletException
    	 * @throws IOException
    	 * @author lyq
    	 * @date:2014-4-25 下午4:05:27
    	 * @version :
    	 */
    	public static void initTokenProcessor(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		//产生随机数
    				TokenProcessor tp=TokenProcessor.getInstance();
    				String token=tp.generateToken();
    				
    				request.getSession().setAttribute("token", token);
    	}
    	
    	/**
    	 * 清除token
    	 * @param request
    	 * @author lyq
    	 * @date:2014-4-25 下午4:03:42
    	 * @version :
    	 */
    	public static void removeTokenProecessor(HttpServletRequest request)
    	{
    		request.getSession().removeAttribute("token");
    	}
    	
    	/**
    	 * 对token的有效性进行判断
    	 * @param request
    	 * @return
    	 * @author lyq
    	 * @date:2014-4-25 下午4:07:03
    	 * @version :
    	 * 判断是否为重复提交
    	 */
    	@SuppressWarnings("unused")
    	public static boolean isTokenValid(HttpServletRequest request) {
    		String client_token=request.getParameter("token");
    		if(client_token==null)
    		{
    			return false;
    		}
    		String server_token=(String)request.getSession().getAttribute("token");
    		if(server_token==null)
    		{
    			return false;
    		}
    		if(!client_token.equals(server_token))
    		{
    			return false;
    		}
    		return true;
    	}
    }
    

      第三个是具体的使用逻辑,我们这里用于注册时的防重提交

    public ActionForward user_registe(ActionMapping mapping, ActionForm form,
    			HttpServletRequest request, HttpServletResponse response)
    			throws UserException {
    		UserForm userform = (UserForm)form;
    		//较验当前令牌与提交的是否相等,如果相同,则允许提交,否则,提交“重复提交”
    if(!AvoidSubmitFormAgain.isTokenValid(request)) { userform.user_mess = "注册请求己提交,不要再重复提交,请重新注册"; return mapping.findForward("user_registe_resubmit_front"); } if(userservice.user_registe(userform.getUser())) { AvoidSubmitFormAgain.removeTokenProecessor(request); userform.user_mess = "用户注册成功,页面跳到登录页面"; request.setAttribute("userform",userform); return mapping.findForward("user_registe_success_front"); }
    }

      

  • 相关阅读:
    常用正则表达式应用
    iOS 通知推送APNS
    IOS生活圈开发练习记录
    [转]定时器
    JavaScript如何在webView跳转到指点的位置
    用imageNamed加载图片产生的问题
    如何再分类中添加属性
    CADisplayLink定时器
    自定义UIBtton类后,在@implementation重写方法的作用
    CAAnimationGroup(组合动画)创建
  • 原文地址:https://www.cnblogs.com/liuyq/p/3689897.html
Copyright © 2020-2023  润新知