JSP自定义JSTL TOKEN 防止表单重复提交

本文介绍了一种在JSP中实现防止表单重复提交的方法,通过生成和验证token来确保每次提交都是用户的新操作,避免了因重复点击或刷新导致的数据错误。
<!-- 在maven中,添加jstl标签库jar包 -->
<dependency>
	<groupId>org.apache.taglibs</groupId>
	<artifactId>taglibs-standard-spec</artifactId>
	<version>1.2.5</version>
</dependency>
<dependency>
	<groupId>org.apache.taglibs</groupId>
	<artifactId>taglibs-standard-impl</artifactId>
	<version>1.2.5</version>
</dependency>
package website;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * token标签工具类
 *
 */
public class TokenTagHelper {

	public static final String SESSION_TOKEN_NAME = "session.token";
	public static final String PAGE_TOKEN_NAME = "page.token";
	private static final Random RANDOM = new SecureRandom();

	/**
	 * 生成token
	 * @param request
	 * @return
	 */
	public static String generateToken(HttpServletRequest request) {
		HttpSession session = request.getSession();
		String token = new BigInteger(165, RANDOM).toString(36).toUpperCase();
		session.setAttribute(SESSION_TOKEN_NAME, token);
		return token;
	}
	
	/**
	 * 验证token
	 * @param request
	 * @return
	 */
	public static boolean isTokenValid(HttpServletRequest request) {
	        HttpSession session = request.getSession(false);

	        if (session == null) {
	            return false;
	        }
	   
	        String sessionToken = (String) session.getAttribute(SESSION_TOKEN_NAME);

	        if (sessionToken == null || "".equals(sessionToken.trim()) ) {
	            return false;
	        }
	        
	        String pageToken = request.getParameter(PAGE_TOKEN_NAME);
	        if (pageToken == null || "".equals(pageToken.trim()) ) {
	            return false;
	        }
	        
	        if(sessionToken.equals(pageToken)){
	        	session.removeAttribute(SESSION_TOKEN_NAME);
	        	return true;
	        }
	        
	        return false;
	    }
}
package website;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * 
 * token标签处理类
 *
 */
public class TokenTag extends SimpleTagSupport {

	@Override
	public void doTag() throws JspException, IOException {
		PageContext pageContext = (PageContext) getJspContext();
		JspWriter out = pageContext.getOut();
		String name = TokenTagHelper.PAGE_TOKEN_NAME;
		String value = TokenTagHelper.generateToken((HttpServletRequest) pageContext.getRequest());
		out.print("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\" /> ");
	} 
	
}
<?xml version="1.0" encoding="UTF-8" ?>

<!-- 在META-INF目录下,创建.tld文件,名字可以随便取,如t.tld -->
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">
        
	<description>custom tag</description> <!-- 可不定义 -->
	<display-name>token</display-name> <!-- 可不定义 -->
	<tlib-version>1.0</tlib-version> 

	<short-name>t</short-name> <!-- 标签前缀 -->
	<uri>http://localhost/jsp/token</uri> <!-- 标签唯一标识 -->

	<tag>
		<name>token</name> <!-- 标签名 -->
		<tag-class>website.TokenTag</tag-class>  <!-- 标签处理类 -->
		<body-content>empty</body-content> <!-- 没有标签体 -->
	</tag>

</taglib>  
package website;

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;

/**
 * token过滤器
 *
 */
public class TokenTagFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) arg0;
		
		//如果是post请求,且页面上放了token标签,则进行token校验
		if ("post".equalsIgnoreCase(request.getMethod())) {
			String pageToken = request.getParameter(TokenTagHelper.PAGE_TOKEN_NAME); 
			if (pageToken != null) {
				boolean isTokenValid = TokenTagHelper.isTokenValid(request);
				if (!isTokenValid) {
					request.setAttribute("msg", "请不要重复提交");
					request.getRequestDispatcher("/error.jsp").forward(request, arg1);
					return;
				}
			}
		}
		
		arg2.doFilter(request, arg1);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

	<!-- 在web.xml增加以下内容-->

	<!-- token过滤器 -->
	<filter>
		<filter-name>tokenTagFilter</filter-name>
		<filter-class>website.TokenTagFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>tokenTagFilter</filter-name>
		<!--<url-pattern>/*</url-pattern>-->
		<url-pattern>*.do</url-pattern>
		<url-pattern>*.jsp</url-pattern>
	</filter-mapping>
  
  	<!-- token标签,如果.tld文件存放在WEB-INF下,则不需要配置该项 -->
  	<jsp-config>
  		<taglib>
  			<taglib-uri>http://localhost/jsp/token</taglib-uri> <!-- 标签唯一标识 -->
  			<taglib-location>/META-INF/t.tld</taglib-location> <!-- .tld存放路径 -->
  		</taglib>
  	</jsp-config>
  
</web-app>
<!-- 在jsp中增加以下内容 -->

<!-- 引用标签类 -->
<%@ taglib prefix="t" uri="http://localhost/jsp/token"  %>

<form action="xxx.do" method="post">
	<t:token/> <!-- 使用token -->
	<input type="submit" value="提交">
</form>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值