【文章标题】山寨版struts的TokenProcessor类
【文章作者】曾健生
【作者邮箱】zengjiansheng1@126.com
【作者QQ】190678908
【作者声明】本人水平有限,失误之处,敬请各位指出。
*******************************************************************************
Struts 1.x中有个很有用的工具类TokenProcessor,在阅读了源代码后根据原理进行了一定程度上的改写,同时也对这个类的编写思路进行阐述。
由于在原代码中要用到另外一个类Globals的常量值,方便起见把需要用到常量值写到山寨版的TokenProcessor类MyTokenProcessor中,内容如下:
//标识session中的属性
public static final String TOKEN_KEY = "newjueqi.net.csdn.session.token.key";
//标识通过表单传递的属性
public static final String PARAM_TOKEN_KEY = "newjueqi.net.csdn.session.param.token.key";
编写MyTokenProcessor类分以下几步:
一.把类变为“单实例模式”
//单例模式
private MyTokenProcessor(){}
private static final MyTokenProcessor myTokenProcessor=new MyTokenProcessor();
public static MyTokenProcessor getInstance()
{
return myTokenProcessor;
}
二.产生一个随机的字符串, 把该字符串放在 Session 中, 并返回
//产生一个随机的字符串, 把该字符串放在 Session 中, 并返回
public String saveToken(HttpServletRequest request){
String tokenStr=null;
//产生一个随机的字符串
tokenStr=this.generateToken(request);
//获取session
HttpSession session=request.getSession();
//把产生的字符串放入到session中
session.setAttribute(TOKEN_KEY, tokenStr);
return tokenStr;
}
其中的generateToken方法用MD5 算法和 sessionId, 系统时间产生一个随机的字符串
private String generateToken(HttpServletRequest request){
String tokenStr=null;
String currentTime=null;
String sessionId=null;
//获取现在系统时间的字符串
currentTime=System.currentTimeMillis()+"";
//获取sessionID
sessionId=request.getSession().getId();
try {
MessageDigest md=null;
//使用MD5算法
md = MessageDigest.getInstance("MD5");
//把系统时间和sessionId都参与MD5运算
md.update( currentTime.getBytes());
md.update( sessionId.getBytes());
//获取MD5值
byte tokenByte[]=md.digest();
//把MD5值转换为16进制字符串
tokenStr=this.toHex(tokenByte);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return tokenStr;
}
在generateToken中使用了一个函数把字节数组变成一个字符串,其中的原理已在本人的博文《从计算机的核心思想探讨一种进制转换的方法》(http://blog.youkuaiyun.com/newjueqi)进行了相关的阐述,这个函数的算法generateToken的过程如图1 所示:
图1
三.检验在 session 域中的 TOKEN_KEY 属性值和表单传递的请求参数的值是否一致。
public boolean isTokenValid(HttpServletRequest request){
//1.先检查session是否存在,如果不存在就返回
HttpSession session=null;
//用getSession()获取session,传入的参数为false
//则表示如果session不存在就不创建新的session
session=request.getSession(false);
if( session==null )
{
return false;
}
//2.检查 Session 中是否有 TOKEN_KEY 属性, 若没有, 返回 false
Object tokenValue=session.getAttribute(TOKEN_KEY);
if( tokenValue==null )
{
return false;
}
//3. 检查表单的隐藏域中是否存在指定的参数值: PARAM_TOKEN_KEY, 若不存在, 返回 false
String paramValue=request.getParameter( PARAM_TOKEN_KEY );
if( paramValue==null )
{
return false;
}
//返回表单的隐藏域指定的参数值和Session域中属性值的比较结果
return tokenValue.toString().equals(paramValue);
}
四.清空 session 中的 TOKEN_KEY 属性
public void resetToken(HttpServletRequest request){
HttpSession session=null;
//获取session的引用
session=request.getSession();
//如果session不为空,则从session中清除TOKEN_KEY 属性
if( session!=null )
{
session.removeAttribute(TOKEN_KEY);
}
}
在附件中的工程是用这个自定义的类实现防止表单的重复提交。
附件下载地址:http://newjueqi.ys168.com/