OSDN Git Service

CSRFインターセプターをマシに。
authorsenju <senju@users.sourceforge.jp>
Sun, 23 Aug 2009 09:26:56 +0000 (18:26 +0900)
committersenju <senju@users.sourceforge.jp>
Sun, 23 Aug 2009 09:26:56 +0000 (18:26 +0900)
期限チェックを実装し、タブブラウザ等に対応。

src/jp/sourceforge/rabbitBTS/interceptors/CSRFInterceptor.java
war/WEB-INF/rabbitBTS-servlet.xml

index 439ac03..42add8f 100644 (file)
 
 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;
@@ -36,6 +38,7 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  * CSRF対策用インターセプター
  */
 public class CSRFInterceptor extends HandlerInterceptorAdapter {
+       private int expireInSecond;
 
        /**
         * POSTの場合チェック処理
@@ -84,17 +87,29 @@ public class CSRFInterceptor extends HandlerInterceptorAdapter {
                }
        }
 
+       /**
+        * チェック用クラス
+        */
        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);
                        }
                }
 
@@ -105,26 +120,62 @@ public class CSRFInterceptor extends HandlerInterceptorAdapter {
                 */
                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;
        }
 
 }
index 2baa492..0bba5d5 100644 (file)
@@ -35,7 +35,9 @@
        <bean class="jp.sourceforge.rabbitBTS.interceptors.AuthenticationInterceptor"
                id="authInterceptor" />
        <bean class="jp.sourceforge.rabbitBTS.interceptors.CSRFInterceptor"
-               id="csrf" />
+               id="csrf">
+               <property name="expireInSecond" value="60" />
+       </bean>
        <bean
                class="org.springframework.orm.jdo.support.OpenPersistenceManagerInViewInterceptor"
                id="openInView">