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>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值