<%@ 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>