由于web服务器要同时处理大量的http请求,所以用户的某个提交会得不到及时的相应。
这样用户会有意无意的重复点击提交,如果没有很好的措施来防止这种情况。会对系统的安全性带来隐患。
常用的防止重复提交的方法有两种:
1.通过javascript代码在客户端浏览器进行处理。
2.在服务器端进行处理。
其中第二种的安全性更高。
以下是一个在服务器端进行的防止用户重复提交的一个实现。
public class TokenProcessor {
private static final String TOKEN_KEY="token";
private static TokenProcessor instance=new TokenProcessor();
public static TokenProcessor getInstance(){
return instance;
}
private long last;
public synchronized boolean isTokenValid(HttpServletRequest request){
HttpSession session=request.getSession(false);
if(null==session){
return false;
}
String attributeToken=(String)session.getAttribute(TOKEN_KEY);
if(attributeToken==null){
return false;
}
resetToken(request);
String parameterToken=(String)request.getParameter(TOKEN_KEY);
if(null==parameterToken){
return false;
}
return attributeToken.equals(parameterToken);
}
public synchronized void resetToken(HttpServletRequest request){
HttpSession session=request.getSession(false);
if(null==session){
return;
}
session.removeAttribute(TOKEN_KEY);
}
public synchronized void saveToken(HttpServletRequest request){
HttpSession session=request.getSession(false);
String token=generateToken(request);
if(token!=null){
session.setAttribute(TOKEN_KEY, token);
}
}
public String generateToken(HttpServletRequest request) {
HttpSession session=request.getSession(false);
byte[] id=session.getId().getBytes();
long current=System.currentTimeMillis();
if(current==last){
current++;
}
last=current;
byte[] now=new Long(current).toString().getBytes();
try {
MessageDigest md=MessageDigest.getInstance("MD5");
md.update(id);
md.update(now);
return toHex(md.digest());
} catch (NoSuchAlgorithmException ex) {
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();
}
public synchronized String getToken(HttpServletRequest request){
HttpSession session=request.getSession(false);
if(session==null){
return null;
}
String token=(String) session.getAttribute(TOKEN_KEY);
if(token==null){
token=generateToken(request);
if(token!=null){
session.setAttribute(TOKEN_KEY, token);
return token;
}else{
return null;
}
}
return token;
}
}
实现原理为:
当用户提交时,参数中会有一个token。在服务器端进行处理的时候,会验证该token。验证成功,则处理。
验证不成功,可以提示用户不能重复提交。
代码比较简单,不做过多说明。