`

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>











分享到:
评论

相关推荐

    自定义标签 防止重复提交

    本文将深入探讨自定义标签在防止重复提交中的实现原理和应用。 首先,我们要理解什么是自定义标签(Custom Tags)。在JavaServer Pages(JSP)中,自定义标签是扩展JSP功能的一种方式,它可以封装复杂的业务逻辑...

    防止表单重复提交

    在Web开发中,表单提交是一项基础且关键的操作,它允许用户向服务器发送数据进行...总的来说,防止表单重复提交是一个多层面、多层次的问题,需要综合运用客户端和服务器端的技术,以确保应用的稳定性和数据的一致性。

    struts2 防止表单重复提交的例子

    在Web开发中,表单重复提交是一个常见的问题,它可能导致数据的不一致性或者服务端处理逻辑的混乱。Struts2框架提供了一种解决方案,即使用Token机制来防止表单的重复提交。以下是对这个主题的详细说明: 1. **表单...

    Struts2解决表单重复提交

    在Web应用中,表单重复提交是一种常见的问题。通常,这种问题发生在用户在提交表单后,由于网络延迟或用户的误操作再次点击提交按钮,或者在表单提交后刷新浏览器页面。这两种情况都可能导致服务器接收到重复的请求...

    Struts2防止重复提交解决方案

    在Struts2中,防止重复提交是一个重要的问题,因为它可能导致数据不一致性和服务器资源的浪费。本文将详细介绍如何在Struts2中解决这个问题,以及相关的技术概念。 首先,我们要理解Struts2中的拦截器(Interceptor...

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

    浅谈利用Session防止表单重复提交 Session是Web应用程序中的一种机制,用于存储用户的会话信息。在Web应用程序中,表单重复...使用Session结合UUID可以有效地防止表单重复提交,提高了Web应用程序的安全性和可靠性。

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

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

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

    在ASP.NET web应用程序中,表单重复提交是一个常见的问题,可能导致数据不一致或者数据库操作的冗余。为了确保用户在提交表单时不会无意或有意地多次发送请求,我们需要实施有效的防止表单重复提交的策略。以下是...

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

    总结起来,Struts2通过重定向策略可以有效地防止表单重复提交,结合其他如Token Session Strategy等方法,可以进一步提高应用的安全性和稳定性。开发者可以根据项目需求选择合适的防重提交方案,确保系统正常运行。

    JavaEE Struts2利用tokenSession防止重复提交

    在JavaEE应用开发中,Struts2框架是一个广泛使用的MVC框架,它提供了一种有效的方式来组织和控制应用程序的行为。然而,随着Web应用的发展,防止重复提交成为一个重要的问题,尤其是在处理金融交易、投票等关键操作...

    ASP.NET中防止刷新页面造成表单重复提交

    ### ASP.NET中防止刷新页面造成表单重复提交 在Web应用程序开发中,特别是在使用ASP.NET进行网站构建时,一个常见的问题是表单重复提交。这通常发生在用户通过按下浏览器的F5键来刷新页面的情况下,此时之前的表单...

    SSH笔记-数据验证、上传下载、避免表单重复提交、自定义拦截器

    总结来说,这个SSH笔记涵盖了Web开发中的关键知识点,包括数据验证确保输入合法性,文件上传下载提供交互性,防止表单重复提交保护数据一致性,以及自定义拦截器增强应用的功能和灵活性。掌握这些技能,将有助于提升...

    Struts2防止表单重复提交示例

    为了防止这种情况,开发者通常会采取一些策略,如在Struts2中使用Token机制。 在Struts2中防止表单重复提交的过程主要包括以下几个步骤: 1. **生成Token**:当用户发起表单请求时,服务器会生成一个唯一的Token并...

    Struts2文件上传下载和表单重复提交问题

    在实际应用中,文件上传和下载以及防止表单重复提交是两个常见的需求,同时也是开发者必须掌握的重要技能。 1. **文件上传** 文件上传功能在Struts2中通过`Struts2`提供的插件来实现,主要依赖于`Apache Commons ...

    Servlet、Struts、SpringMVC对于表单重复提交的解决方案

    总结来说,Servlet、Struts和SpringMVC都提供了各自的解决方案来防止表单重复提交,主要方法包括使用Session、令牌机制、重定向和拦截器等。开发者可以根据项目需求选择合适的方式来实现,确保应用的稳定性和数据...

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

    综上所述,理解并掌握Struts框架中的数据回显、模型驱动以及防止表单重复提交的原理和实现方法,对于提升Java Web应用的开发效率和质量具有重要意义。在实际开发中,应灵活运用这些技术,以满足项目需求,打造稳定...

    Struts2 表单 重复提交

    在Eclipse项目中,`Struts_0304_Interceptor_token`可能包含了一个示例项目,展示了如何配置和使用Struts2的token拦截器来防止表单重复提交。通过查看该项目的代码和配置文件,你可以更深入地理解和学习这一功能。

    struts token机制解决表单重复提交

    总的来说,Struts Token机制通过维护一个临时的、一次性使用的Token,有效地解决了Web应用中的表单重复提交问题,提高了系统的稳定性和安全性。在实际开发中,应根据项目需求灵活运用并优化此机制。

Global site tag (gtag.js) - Google Analytics