`

session 的应用——防止表单重复提交——2.0版(使用了Struts1 中的重复提交组件: TokenProcessor和自定义标签)

阅读更多
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 这里使用的是自定义标签 -->
<%@ taglib prefix="syh" uri="http://java.syh.com/jsp/syh/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>

<script type="text/javascript">

	//点击 "提交" 按钮, 只能点击一次
	var flag = true;
	
	
	function token(btn){
		if(flag){
			flag = false;
			return true;
		}else{
			alert('已经提交过了');
		}
	}
	
	/*
	下面的JS代码对 IE 不使用,对于 FF
	function token2(btn){
		if(flag){
			btn.disabled = true;
			return true;
		}
	}
	*/
	
</script>
</head>
<body>

		<!--  
			TokenProcessor.getInstance().saveToken(request)
			
			1. 生成一个随机字符串, 可以保证其唯一
			2. 把该字符串放在 Session 域中
			3. 返回该字符串
		-->
		
	<form action="LoginServlet" method="post" id="regForm">
		<!-- 这里使用的是自定义标签 -->
		<syh:token/>
		<table border="1">
			<tr>
				<td>Name:</td>
				<td>
					<input type="text" name="name"/>
				</td>
			</tr>
			
			<tr>
				<td>Password:</td>
				<td>
					<input type="password" name="password"/>
				</td>
			</tr>
			
			<tr rowspan="2">
				<td>
					<input type="submit" value="Submit" onclick="return token2(this);"/>
				</td>
				<td>
					<input type="reset" value="Reset"/>
				</td>
			</tr>
		</table>
	</form>

</body>
</html>



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

	注册成功!

</body>
</html>



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h4>表单已经提交!请不要多次提交!</h4>

</body>
</html>



package com.syh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

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

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		try {
			Thread.sleep(3000) ;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			//模拟网速
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		//1. 检验 Token 是否可用
		boolean flag = TokenProcessor.getInstance().isTokenValid(request) ;
		//2. 去除 Session 中的 Token 标记
		if(flag) {
			TokenProcessor.getInstance().resetToken(request) ;
		}else {
			System.out.println("重复提交");
			request.getRequestDispatcher("/error.jsp").forward(request, response) ;
			return ;
		}
		
		String name = request.getParameter("name") ;
		System.out.println("添加成功-->" + name);
		
		request.getRequestDispatcher("/success.jsp").forward(request, response) ;
	}

}




package com.syh.servlet;

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

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class TokenProcessor extends SimpleTagSupport{
	
	@Override
	public void doTag() throws JspException, IOException {

		PageContext pageContext = (PageContext) getJspContext();
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
		
		String output = "<input type='hidden' name='" + TOKEN_KEY + "' value='" + saveToken(request) + "'/>";
		pageContext.getOut().print(output);
	}
	
	public static final String TAGLIB_PACKAGE = "org.apache.struts.taglib.html";
	
	public static final String TRANSACTION_TOKEN_KEY =
        "org.apache.struts.action.TOKEN";
	
	public static final String TOKEN_KEY = TAGLIB_PACKAGE + ".TOKEN";
	
    private static TokenProcessor instance = new TokenProcessor();

    private long previous;

    public TokenProcessor() {
        super();
    }

    public static TokenProcessor getInstance() {
        return instance;
    }

    public synchronized boolean isTokenValid(HttpServletRequest request) {
        return this.isTokenValid(request, false);
    }

    public synchronized boolean isTokenValid(HttpServletRequest request,
        boolean reset) {
        // Retrieve the current session for this request
        HttpSession session = request.getSession(false);

        if (session == null) {
            return false;
        }

        String saved =
            (String) session.getAttribute(TRANSACTION_TOKEN_KEY);

        if (saved == null) {
            return false;
        }

        if (reset) {
            this.resetToken(request);
        }

        String token = request.getParameter(TOKEN_KEY);

        if (token == null) {
            return false;
        }

        return saved.equals(token);
    }

    public synchronized void resetToken(HttpServletRequest request) {
        HttpSession session = request.getSession(false);

        if (session == null) {
            return;
        }

        session.removeAttribute(TRANSACTION_TOKEN_KEY);
    }

    public synchronized String saveToken(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String token = generateToken(request);

        if (token != null) {
            session.setAttribute(TRANSACTION_TOKEN_KEY, token);
        }
        
        return token;
    }

    public synchronized String generateToken(HttpServletRequest request) {
        HttpSession session = request.getSession();

        return generateToken(session.getId());
    }

    public synchronized String generateToken(String id) {
        try {
            long current = System.currentTimeMillis();

            if (current == previous) {
                current++;
            }

            previous = current;

            byte[] now = new Long(current).toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(id.getBytes());
            md.update(now);

            return toHex(md.digest());
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    private String toHex(byte[] buffer) {
        StringBuffer sb = new StringBuffer(buffer.length * 2);

        for (int i = 0; i < buffer.length; i++) {
            sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
            sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
        }

        return sb.toString();
    }
}




<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
  <description>MyTag 1.0 core</description>
  <display-name>MyTag core</display-name>
  <tlib-version>1.0</tlib-version>
  <short-name>syh</short-name>
  <uri>http://java.syh.com/jsp/syh/core</uri>

	<tag>
		<name>token</name>
		<tag-class>com.syh.servlet.TokenProcessor</tag-class>
		<body-content>empty</body-content>
	</tag>

  

</taglib>











分享到:
评论

相关推荐

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

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

    客户端防表单重复提交和服务器端session防表单重复提交

    客户端防表单重复提交和服务器端session防表单重复提交.

    java实现防止表单重复提交

    服务器端避免表单的重复提交,利用同步令牌来解决重复提交的基本原理如下:(1)用户访问提交数据的页面,服务器端在这次会话中,创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域的值,随表单一起发送到...

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

    主要介绍了浅谈利用Session防止表单重复提交,简单介绍表单重复提交的情况,分析,以及解决方法代码示例,具有一定借鉴价值,需要的朋友可以了解下。

    JavaEE Struts2利用tokenSession防止重复提交

    JavaEE Struts2利用tokenSession防止重复提交

    struts1.2自定义标签之session验证

    视频第二部分共两部分 下载前请阅读博客文章详细 博文链接:https://dlivan.iteye.com/blog/68374

    PHP使用token防止表单重复提交的方法

    本文实例讲述了PHP使用token防止表单重复提交的方法。分享给大家供大家参考,具体如下: &lt;?php /* * PHP使用token防止表单重复提交 * 此处理方法纯粹是为了给初学者参考 */ session_start(); function set_token...

    PHP防止表单重复提交的几种常用方法汇总

    本文较为详细的汇总了PHP防止表单重复提交的几种常用方法,在PHP程序开发中有着很高的实用价值。具体方法如下: 1. 使用JS让按钮在点击一次后禁用(disable)。采用这种方法可以防止多次点击的发生,实现方式较简单...

    php通过记录IP来防止表单重复提交方法分析

    这个原理比较的简单就是用户第一次提交时我们记录提交用户的IP地址,这样如果用户在固定时间内再次提交表单就会提示重复提交了,这种做法通常用于在顶一下,支持一下这种应用中了,在防止数据重复提交是一个非常不好的...

    防止页面重复提交demo

    通过前端控制和后台session存储的随机token防止页面重复提交。

    PHP+Session防止表单重复提交的解决方法

    主要介绍了PHP+Session防止表单重复提交的解决方法,需要的朋友可以参考下

    asp自定义表单系统

    自定义表单系统使用说明: 后台地址:biaodan/admin/admin_login.asp,第一次打开本后台,会提示重新安装目录,安装好,删除biaodan/install.asp文件后,即可使用。后台用户名:admin,后台密码:admin。 默认开启...

    php表单加入Token防止重复提交的方法分析

    Token一般用在两个地方——防止表单重复提交、anti csrf攻击(跨站点请求伪造)。 两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,...

    struts中自定义的tag的Java类中如何获得session

    HttpSession session = this.pageContext.getSession(); 资源的方法同上。故不用下载资源。

    php解决和避免form表单重复提交的几种方法

    先看一下有哪些情况下回导致表单重复提交呢,知道哪些情况下可能会出现表单重复提交就可以从根源处理表单重复提交的情况了。 下面的情况就会导致表单重复提交:  点击提交按钮两次。  点击刷新按钮。  使用浏览器...

    自己实现的spring-session

    如果有sessionId,就去redis中查看是否有此id的记录,如果没有就新建session,如果有,还是新建session,并把redis中此session的相关数据赋值给新建的session,最后保存sessionId到cookie,cookie的maxAge设置为-1,...

    web自定义标签简单应用Tag.zip

    web自定义标签简单应用,采用自定义标签的技术实现一个JSP页面标签,实现页面输出要求为:当上午访问为“上午好,欢迎您:XXX”,下午访问为“下午好,欢迎您:XXX”。其中XXX为从session中取出当前系统的用户名。

Global site tag (gtag.js) - Google Analytics