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>