package jp.sourceforge.rabbitBTS.interceptors;
+import java.util.ArrayList;
import java.util.Date;
-import java.util.LinkedList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
* CSRF対策用インターセプター
*/
public class CSRFInterceptor extends HandlerInterceptorAdapter {
+ private int expireInSecond;
/**
* POSTの場合チェック処理
}
}
+ /**
+ * チェック用クラス
+ */
class CsrfChecker {
private final HttpServletRequest req;
- private List<Object> tokenList;
+ private Map<String, Date> tokens;
+ /**
+ * コンストラクタ
+ *
+ * <p>
+ * セッションにトークンのリストが存在しない場合、新規に作成しセッションに保存する。
+ *
+ * @param request
+ */
+ @SuppressWarnings("unchecked")
public CsrfChecker(HttpServletRequest request) {
this.req = request;
- this.tokenList = (List) request.getSession().getAttribute(
- "tokenList");
- if (this.tokenList == null) {
- this.tokenList = new LinkedList<Object>();
- request.getSession().setAttribute("tokenList", this.tokenList);
+ this.tokens = (Map<String, Date>) request.getSession()
+ .getAttribute("tokens");
+ if (this.tokens == null) {
+ this.tokens = new HashMap<String, Date>();
+ request.getSession().setAttribute("tokens", this.tokens);
}
}
*/
public String saveNewToken() {
final String token = RandomStringUtils.randomAlphanumeric(128);
- this.tokenList.add(token);
- this.tokenList.add(new Date());
-
+ this.tokens.put(token, new Date());
return token;
}
+ /**
+ * チェックを行う
+ *
+ * @return 正しいパラメータが送信された場合true
+ */
public boolean checkTokenValid() {
final String reqToken = this.req.getParameter("secureToken");
+ final Date datenow = new Date();
+ // トークンチェック
boolean found = false;
- for (int i = 0; i < this.tokenList.size(); i += 2) {
- final String token = (String) this.tokenList.get(i);
- if (token.equals(reqToken)) {
- // TODO:期限チェック
- found = true;
- break;
+ if (this.tokens.containsKey(reqToken)) {
+ found = checkExpire(datenow, this.tokens.get(reqToken));
+ }
+
+ // 削除チェック
+ if (this.tokens.size() > 30) {
+ final List<String> removeList = new ArrayList<String>();
+ for (final String token : this.tokens.keySet()) {
+ final Date created = this.tokens.get(token);
+ if (!this.checkExpire(datenow, created)) {
+ // 期限切れの場合
+ removeList.add(token);
+ Sht.log(this).finer("delete token: " + token);
+ }
+ }
+ for (final String token : removeList) {
+ this.tokens.remove(token);
}
}
- // TODO:期限切れ削除
+
return found;
}
+
+ /**
+ * 期限切れかチェックする。
+ *
+ * @param datenow
+ * @param created
+ * @return 期限以内の場合true
+ */
+ private boolean checkExpire(Date datenow, Date created) {
+ final long ageInMils = datenow.getTime() - created.getTime();
+ return ageInMils / 1000 < CSRFInterceptor.this.expireInSecond;
+ }
+ }
+
+ /**
+ * @param expireInSecond
+ * the expireInSecond to set
+ */
+ public void setExpireInSecond(int expireInMinute) {
+ this.expireInSecond = expireInMinute;
}
}