一、使用方法
1、 假如你要提交的頁面為toSubmit.jsp;
2、 在打開toSubmit.jsp的Action1中加入:saveToken(request),例如
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
//生成同步令牌
saveToken(request);
return mapping.findForward("toSubmit");
} |
3、 在提交toSubmit.jsp的Action2中加入:isTokenValid(request, true),例如:
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// 驗證同步令牌
if (isTokenValid(request, true)) {
//執行提交操作
}else {
// 重復提交
return mapping.findForward("Error");
}
} |
4、 使用注意:toSubmit.jsp中的form必須使用struts的標簽<html:form>。
二、基本原理
第一步、在session中放入同步令牌
在Action1中加入了saveToken(request)的方法后,調用TokenProcessor類的saveToken方法如下:
public synchronized void saveToken(HttpServletRequest request) {
HttpSession session = request.getSession();
String token = generateToken(request);
if (token != null) {
session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);
}
} |
很明顯在session中放入了同步令牌,名稱為Globals.TRANSACTION_TOKEN_KEY。
第二步、在頁面創建hidden元素
當應用服務器初始化toSubmit.jsp頁面遇到標簽<html:form>時,便會調用struts的FormTag類,其中有一個方法:
protected String renderToken() {
StringBuffer results = new StringBuffer();
HttpSession session = pageContext.getSession();
if (session != null) {
String token =
(String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
if (token != null) {
results.append("<input type=\"hidden\" name=\"");
results.append(Constants.TOKEN_KEY);
results.append("\" value=\"");
results.append(token);
if (this.isXhtml()) {
results.append("\" />");
} else {
results.append("\">");
}
}
}
return results.toString();
} |
其意為:當檢測到session中的Globals.TRANSACTION_TOKEN_KEY不為空時,在toSubmit.jsp頁面創建元素:
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value=""> |
名稱為:org.apache.struts.taglib.html.TOKEN就是Constants.TOKEN_KEY;
值為:session中的Globals.TRANSACTION_TOKEN_KEY的值,即為同步令牌值。
第三步、驗證同步令牌
在Action2中加入isTokenValid方法,實際上是調用TokenProcessor類的isTokenValid方法如下:
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;
}
// Retrieve the transaction token from this session, and
// reset it if requested
String saved = (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
if (saved == null) {
return false;
}
if (reset) {
this.resetToken(request);
}
// Retrieve the transaction token included in this request
String token = request.getParameter(Constants.TOKEN_KEY);
if (token == null) {
return false;
}
return saved.equals(token);
} |
它首先取得session中的令牌值,然后resetToken,再從頁面hidden元素取來令牌值,進行比較,如果相等則為第一次,不等則為重復提交。
其中resetToken方法如下:
public synchronized void resetToken(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(Globals.TRANSACTION_TOKEN_KEY);
} |
posted on 2006-03-08 21:07
野草 閱讀(2726)
評論(3) 編輯 收藏 所屬分類:
2shtv