`

防止表单重复提交

    博客分类:
  • Web
 
阅读更多

一、利用js,表单提交后马上使按钮失效

<input type="button" value="提交" onclick="this.disabled=true;this.form.submit()"> 

 
二、利用token防止表单重复提交

    Filter

package com.web;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ArrayUtils;

public class TokenRequestFilter implements Filter {
	   
    private String[] addUrls; // 需要增加 TOKEN 的页面  
    private String[] validUrls;// 需要验证TOEKN 的页面  
    private String processUrl; // TOKEN 验证失败处理的页面  
    FilterConfig filterConfig = null;  
    
    // 实例化 token 生成器  
    private TokenGenerator tokenGenerator = new SimpleTokenGenerator(); 
    

	public void destroy() {
		this.filterConfig = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// 获取请求路径  
        String path = getRelativePath((HttpServletRequest) request);  
        // 如果路径存在增加的urls列表里面,则向客户端增加一个token 参数  
        if (ArrayUtils.contains(addUrls, path)) {  
        	tokenGenerator.save((HttpServletRequest) request,  
                    (HttpServletResponse) response);  
        }  
        // 如果路径存在验证urls列表里面 这获取客户端 token 参数做验证  
        if (ArrayUtils.contains(validUrls, path)) {  
            if (!tokenGenerator.validate((HttpServletRequest) request,  
                    (HttpServletResponse) response)) {  
                // 验证没有通过则跳转到错误处理页面  
                ((HttpServletResponse) response)  
                        .sendRedirect(processUrl);  
                return;  
            }  
        }  
        // 到了这里说明验证已经通过,则将客户端 token 删除 下次提交客户端cookie token 为空 重复提交则失败  
        if (ArrayUtils.contains(validUrls, path)) {  
            tokenGenerator.remove((HttpServletRequest) request,  
                    (HttpServletResponse) response);  
        }  
        chain.doFilter(request, response);  
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		String _splitChar = filterConfig.getInitParameter("splitChar");
		String _addUrls = filterConfig.getInitParameter("addUrls");
		String _validUrls = filterConfig.getInitParameter("validUrls");
		processUrl = filterConfig.getInitParameter("processUrl") ;
		filterConfig.getInitParameter("processUrl");
		if(null != _addUrls && "".equals(_addUrls)){
			addUrls = _addUrls.split(_splitChar);
		}
		if(null != _validUrls && "".equals(_validUrls)){
			validUrls = _validUrls.split(_splitChar);
		}
		
	}
	
	protected String getRelativePath(HttpServletRequest request) {   
		return request.getRequestURL().toString();

    }  

}

 Token接口

package com.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface TokenGenerator {
	  /** 
     * 增加 TOKEN  
     */  
    public String save(HttpServletRequest request, HttpServletResponse response);  
      
    /** 
     * 删除TOKEN 
     */  
    public void remove(HttpServletRequest request, HttpServletResponse response);  
      
    /** 
     * 验证TOKEN 是否有效 验证成功应当手动调用 remove 方法 手动从COOKIE中清除TOKEN 
     */  
    public boolean validate(HttpServletRequest request, HttpServletResponse response); 
}

 Token实现

package com.web;

import java.util.UUID;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

public class SimpleTokenGenerator implements TokenGenerator {

	 /** 
     * 默认TOOKEN 名称 
     */  
    private final static String FORM_TOEKN_NAME = "_form_token";  
  
    public boolean validate(HttpServletRequest request,  
            HttpServletResponse response) {  
        String paramString = request.getParameter(FORM_TOEKN_NAME);  
        if (StringUtils.isBlank(paramString)) {  
            return false;  
        }  
        String value = get(request);  
        if (StringUtils.isBlank(value)) {  
            return false;  
        }  
        return value.equals(paramString);  
    }  
  
    public String save(HttpServletRequest request, HttpServletResponse response) {  
        String value = StringUtils.remove(UUID.randomUUID().toString(), "-");  
        if (value != null) {  
            set(request, response, value);  
        }  
        return value;  
    }  
  
    public void remove(HttpServletRequest request, HttpServletResponse response) {  
        String value = get(request);  
        if (value != null) {  
            cancle(request, response);  
        }  
    }  
  
    /** 
     * 从cookie中获取TOKEN 
     *  
     * @param request 
     * @return 
     */  
    private String get(HttpServletRequest request) {  
        Cookie cookie = CookieUtils.getCookie(request, FORM_TOEKN_NAME);  
        return cookie == null ? null : cookie.getValue();  
    }  
  
    /** 
     * 设置 TOKEN 到 COOKIE 当中 
     *  
     * @param request 
     * @param response 
     * @param value 
     */  
    private void set(HttpServletRequest request, HttpServletResponse response,  
            String value) {  
        if (value != null) {  
            CookieUtils.addCookie(request, response, FORM_TOEKN_NAME, value,  
                    -1, null);  
        }  
        if (value != null) {  
            request.setAttribute(FORM_TOEKN_NAME, value);  
        }  
    }  
  
    /** 
     * 从COOKIE中清楚TOKEN 
     *  
     * @param request 
     * @param response 
     */  
    private void cancle(HttpServletRequest request, HttpServletResponse response) {  
        CookieUtils.cancleCookie(request, response, FORM_TOEKN_NAME, null);  
    }  
}

 CookieUtils

package com.web;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

public class CookieUtils {
	
    /** 
     * 获得cookie 
     *  
     * @param request 
     *            HttpServletRequest 
     * @param name 
     *            cookie name 
     * @return if exist return cookie, else return null. 
     */  
    public static Cookie getCookie(HttpServletRequest request, String name) {  
        Cookie[] cookies = request.getCookies();  
        if (cookies != null && cookies.length > 0) {  
            for (Cookie c : cookies) {  
                if (c.getName().equals(name)) {  
                    return c;  
                }  
            }  
        }  
        return null;  
    }  
  
    /** 
     * 根据部署路径,将cookie保存在根目录。 
     *  
     * @param request 
     * @param response 
     * @param name 
     * @param value 
     * @param expiry 
     * @param domain 
     * @return 
     */  
    public static Cookie addCookie(HttpServletRequest request,  
            HttpServletResponse response, String name, String value,  
            Integer expiry, String domain) {  
        Cookie cookie = new Cookie(name, value);  
        if (expiry != null) {  
            cookie.setMaxAge(expiry);  
        }  
        if (StringUtils.isNotBlank(domain)) {  
            cookie.setDomain(domain);  
        }  
        String ctx = request.getContextPath();  
        cookie.setPath(StringUtils.isBlank(ctx) ? "/" : ctx);  
        response.addCookie(cookie);  
        return cookie;  
    }  
  
    /** 
     * 取消cookie 
     *  
     * @param request 
     * @param response 
     * @param name 
     * @param domain 
     */  
    public static void cancleCookie(HttpServletRequest request,  
            HttpServletResponse response, String name, String domain) {  
        Cookie cookie = new Cookie(name, "");  
        cookie.setMaxAge(0);  
        String ctx = request.getContextPath();  
        cookie.setPath(StringUtils.isBlank(ctx) ? "/" : ctx);  
        if (StringUtils.isNotBlank(domain)) {  
            cookie.setDomain(domain);  
        }  
        response.addCookie(cookie);  
    }  
}

 XML配置

<filter>  
        <filter-name>tokenRequestFilter</filter-name>  
        <filter-class>com.web.TokenRequestFilter</filter-class>  
        <init-param>  
            <param-name>splitChar</param-name>  
            <param-value>@</param-value>  
        </init-param>  
        <init-param>  
            <param-name>addUrls</param-name>  
            <param-value>/member/forgot_password.html;/login.html</param-value>  
        </init-param>  
        <init-param>  
            <param-name>validUrls</param-name>  
            <param-value>/member/forgot_password.jhtml;/login.jhtml</param-value>  
        </init-param>  
        <init-param>  
            <param-name>processUrl</param-name>  
            <param-value>/member/tip.html</param-value>  
        </init-param>  
    </filter>  
  
    <filter-mapping>  
        <filter-name>tokenRequestFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

 

分享到:
评论

相关推荐

    springboot2.1+redis+拦截器 防止表单重复提交

    在现代Web应用开发中,防止表单重复提交是一项重要的任务,因为这可能导致数据不一致性和服务器资源浪费。本文将深入探讨如何使用Spring Boot 2.1、Redis和拦截器来实现这一功能。以下是对这个主题的详细解释: ...

    javascript方式防止表单重复提交

    在Web开发中,表单重复提交是一个常见的问题,可能导致数据的冗余或错误。JavaScript作为客户端脚本语言,可以通过多种策略来防止用户意外或恶意地多次提交表单。以下是一些关键的知识点: 1. **禁用提交按钮**:最...

    防止表单重复提交(asp.net )

    为了确保用户在提交表单时不会无意或有意地多次发送请求,我们需要实施有效的防止表单重复提交的策略。以下是一些关键知识点: 1. **表单重复提交的类型**: - **用户行为**:用户可能意外按下刷新按钮,导致已...

    防止表单重复提交的方法(简单的token方式)

    防止表单重复提交的方法(简单的token方式),内附实现代码及实现思路。

    thinkphp3.2 防止表单重复提交

    在Web开发中,防止表单重复提交是一个重要的问题,它能确保用户操作的唯一性和数据的一致性。ThinkPHP 3.2 是一个基于MVC模式的PHP开发框架,提供了丰富的功能来帮助开发者构建安全、高效的应用。在这个场景中,我们...

    springboot+redis+AOP 防止表单重复提交

    AOP是面向切面编程,允许开发者定义“切面”,这些切面可以封装跨越多个对象的行为,如日志记录、事务管理或,就像在这个场景中,防止表单重复提交。AOP的核心概念是“切点”(Pointcut)和“通知”(Advice)。切点...

    浅谈利用Session防止表单重复提交

    浅谈利用Session防止表单重复提交 Session是Web应用程序中的一种机制,用于存储用户的会话信息。在Web应用程序中,表单重复提交是一个常见的问题,可能会导致数据库中产生冗余数据,浪费数据库资源。利用Session...

    自定义注解解决API接口幂等设计防止表单重复提交(生成token存放到redis中)

    为了解决这一问题,我们可以采用自定义注解结合Redis来实现一个防止表单重复提交的解决方案。 首先,让我们理解自定义注解的核心思想。注解是一种元数据,它提供了在代码中添加信息的方式,这些信息可以被编译器或...

    struts2防止表单重复提交--重定向

    下面将详细解释Struts2如何通过重定向来防止表单重复提交。 首先,理解表单重复提交的场景:用户在提交表单后,由于网络延迟或其他原因,可能会无意中多次点击提交按钮。如果服务器没有处理这些重复请求,那么相同...

    Struts2防止表单重复提交示例

    在Struts2中防止表单重复提交的过程主要包括以下几个步骤: 1. **生成Token**:当用户发起表单请求时,服务器会生成一个唯一的Token并将其存储在服务器的会话(Session)中,同时将这个Token作为隐藏字段放入到HTML...

    redis专栏 002 springboot redis 防止表单重复提交

    使用Redis和Spring Boot来防止表单重复提交的基本思路是:在接收到表单提交请求后,生成一个唯一的请求标识(例如,基于UUID),并将其作为键存储到Redis中,设置一个适当的过期时间。当服务器接收到新的请求时,会...

    几种防止表单重复提交的方法

    几种防止表单重复提交的方法 禁掉提交按钮。表单提交后使用Javascript使提交按钮disable。这种方法防止心急的用户多次点击按钮。但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了。 我之前的文章曾说...

    struts2利用token防止表单重复提交(源代码)

    struts2防止表单重复提交,利用struts的拦截器tokenSession,轻轻松松解决表单重复提交的问题。 附件为源代码,后台延迟了3秒,可直接在web服务器下部署运行,输入用户名和密码后,多点几次提交按钮,然后看控制台...

    JavaScript防止表单重复提交代码,指定时间内禁止重复点击.zip

    在Web开发中,防止表单重复提交是一个常见的需求,特别是在涉及关键操作如用户登录、支付等场景下。JavaScript作为客户端脚本语言,可以用来实现这一功能,以避免用户无意或恶意地连续点击提交按钮,导致服务器接收...

    struts数据回显、模型驱动、防止表单重复提交

    本主题将深入探讨Struts框架中的数据回显、模型驱动以及如何防止表单重复提交,这些都是在实际开发中非常关键且实用的技术点。 1. 数据回显: 数据回显是指在用户提交表单后,服务器端处理数据并返回结果页面时,将...

Global site tag (gtag.js) - Google Analytics