分享

表单重复提交的处理方案(其中服务器处理 模拟struts)

 sd9527 2011-04-07
/**
*模拟struts的令牌机制,写一个模拟的令牌类
*/
package token;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

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

/**
 * 服务器放置表单重复提交
 * @author Administrator
 * 单例
 */
public class TokenProcessor {
    static final String TOKEN_KEY="web_submit_token";
    
    private static TokenProcessor instance=new TokenProcessor();
   
    /**
     * 最近一次生成令牌值的时间戳
     */
    private long previous;
   
    /**
     * getInstance() 方法得到单例类的实例
     * @return
     */
    public static TokenProcessor getInstance(){
       
        return instance;
    }
    /**
     * 判断请求参数中的令牌值是否有效
     */
    public synchronized boolean isTokenValid(HttpServletRequest request){
        //获取当前请求对应的session
        HttpSession session=request.getSession(false);
        if(null == session){
            return false;
        }
        //从session中取出令牌值
        String saved=(String) session.getAttribute(TOKEN_KEY);
        if(null == saved){
            return false;
        }
        //清除session中的令牌值
        resetToken(request);
        //得到请求参数中的令牌值
        String token=(String) request.getParameter(TOKEN_KEY);
        if(null == token){
            return false;
        }
        //当两者都不为null  就比较是否相等
        return saved.equals(token);
    }
   
   
    /**
     * 清除session中的令牌值
     */
    public synchronized void resetToken(HttpServletRequest request){
        HttpSession session=request.getSession(false);
        if(session == null){
            return;
        }
        session.removeAttribute(TOKEN_KEY);
    }
    /**
     * 产生一个新的令牌值,保存到session中
     * 如果当前session不存在,则创建一个session
     */
    public synchronized void saveToken(HttpServletRequest request){
        HttpSession session=request.getSession();
        String token=generateToken(request);
        if(token != null){
            session.setAttribute(TOKEN_KEY, token);
        }
    }
   
    /**
     * 从session中得到一个令牌值,如果session中
     * 没有保存令牌值,就生成一个新的令牌值
     */
    public synchronized String getToken(HttpServletRequest request){
        HttpSession session=request.getSession(false);
        if(null == session){
            return null;
        }
        String token=(String) session.getAttribute(TOKEN_KEY);
        if(null == token){
            token=generateToken(request);
            if(token != null){
                session.setAttribute(TOKEN_KEY, token);
                return token;
            }else{
                return null;
            }
        }
        return token;
    }
    /**
     * 根据会话的ID和当前的系统时间生成一个唯一的令牌
     */
    public synchronized String generateToken(HttpServletRequest request){
        HttpSession session=request.getSession();
        try{
            byte[] id=session.getId().getBytes();
            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);
            md.update(now);
            return toHex(md.digest());
        }catch(NoSuchAlgorithmException e){
            e.printStackTrace();
            return null;
        }
    }
   
    /**
     * 将一个字节数组转换成一个十六进制的字符串
     * @param digest
     * @return
     */
    private String toHex(byte[] digest) {
        StringBuffer sb=new StringBuffer(digest.length*2);
        for(int i=0;i<digest.length;i++){
            sb.append(Character.forDigit((digest[i] & 0xf0)>>4, 16));
            sb.append(Character.forDigit(digest[i] & 0x0f, 16));
        }
        return sb.toString();
    }
}

/**
*servlet中的使用 说明
*/
package servlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import token.TokenProcessor;

public class LoginServlet extends HttpServlet {
    int count = 0;

    @Override
    protected void service(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");

        PrintWriter pw = response.getWriter();
        String to=(String) request.getParameter("web_submit_token");
        System.out.println("表单令牌:"+to);
        String old=(String) request.getSession().getAttribute("web_submit_token");
        System.out.println("ses令牌:"+old);
        TokenProcessor processor = TokenProcessor.getInstance();
        if (processor.isTokenValid(request)) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("submit:" + count);
            if (count % 2 == 1) {
                count = 0;
            } else {
                count++;
            }
            pw.println("SUCCESS");
        }else{
            processor.saveToken(request);
            pw.println("您已经提交了表单,不能重复提交!");
        }
        
        pw.close();
    }

}
/**
*jsp 页面中的设置
*/
 <%@ page language="java"  import="token.TokenProcessor" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www./TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>处理重复登录问题</title>
<script type="text/javascript">
    var checkSubmitFlg=true;
    function checkSubmit(){
    /*
        if(checkSubmitFlg){
            document.getElementById("fm").submit();
            checkSubmitFlg=false;
        }else{
            alert("您已经提交了表单,不能重复提交!");
        }
    */
    }
</script>
</head>
<body>
    <%TokenProcessor processor=TokenProcessor.getInstance();
      String token=processor.getToken(request);
    %>
    <form action="login" method="post" name="fm" id="fm">
        <input type="hidden" name="web_submit_token" value=<%=token %> />
        
        用户名:<input type="text" name="name"/>
        密码:<input type="password" name="pwd"/>
        <!-- <input type="button" value="提交" onclick="checkSubmit();"/> -->
        <input type="submit" value="sub"/>
    </form>
</body>
</html>
/**
*web.xml的配置
*/
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
    xmlns="http://java./xml/ns/javaee"
    xmlns:xsi="http://www./2001/XMLSchema-instance"
    xsi:schemaLocation="http://java./xml/ns/javaee
    http://java./xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>servlets.LoginServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多