From de3d25282162daf1e6edc77fad353cbe5a8b043a Mon Sep 17 00:00:00 2001 From: Koda Date: Thu, 2 Nov 2017 06:49:35 +0900 Subject: [PATCH 1/6] Change version to develop next version --- .gitignore | 2 + pom.xml | 16 +++--- .../project/web/common/InvokeSearch.java | 9 ++++ .../project/web/control/ApiControl.java | 46 ---------------- .../support/project/web/control/Control.java | 22 +++++++- .../project/web/control/GetApiControl.java | 52 +++++++++++++++++++ .../org/support/project/web/dao/UsersDao.java | 2 +- .../support/project/web/logic/UserLogic.java | 15 ++++++ .../GroupsDao_selectAdminOnKeyword.sql | 2 +- .../GroupsDao_selectMyGroupOnKeyword.sql | 2 +- .../GroupsDao/GroupsDao_selectOnKeyword.sql | 2 +- .../project/web/config/AppconfigTest.java | 1 - 12 files changed, 111 insertions(+), 60 deletions(-) create mode 100644 src/main/java/org/support/project/web/control/GetApiControl.java diff --git a/.gitignore b/.gitignore index 81cd27f..3630c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .project .settings .checkstyle +.idea +web.iml diff --git a/pom.xml b/pom.xml index d606492..f93329e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.support-project web - 1.11.1 + 1.12.0-SNAPSHOT jar web @@ -59,13 +59,13 @@ org.support-project common - 1.11.0 + 1.12.0-SNAPSHOT com.h2database h2 - 1.4.183 + 1.4.196 provided @@ -91,27 +91,27 @@ commons-fileupload commons-fileupload - 1.3.1 + 1.3.3 org.apache.directory.api api-all - 1.0.0-M30 + 1.0.0 com.googlecode.owasp-java-html-sanitizer owasp-java-html-sanitizer - 20160827.1 + 20171016.1 + com.google.guava guava - 19.0 + 20.0 - diff --git a/src/main/java/org/support/project/web/common/InvokeSearch.java b/src/main/java/org/support/project/web/common/InvokeSearch.java index 74932fc..eef0903 100644 --- a/src/main/java/org/support/project/web/common/InvokeSearch.java +++ b/src/main/java/org/support/project/web/common/InvokeSearch.java @@ -159,8 +159,17 @@ private void addTarget(Class class1, Method method, String targetPackageName, } InvokeTarget invokeTarget = new InvokeTarget(class1, method, targetPackageName, classSuffix, new LinkedHashMap<>()); if (invokeTargets.containsKey(key)) { + InvokeTarget exists = invokeTargets.get(key); + if (exists.getTargetClass().getName().equals(invokeTarget.getTargetClass().getName()) + && exists.getTargetMethod().getName().equals(invokeTarget.getTargetMethod().getName())) { + //なぜか、同じクラスの同じメソッドが二回登録されることがあるのでスキップ + LOG.info("same target duplicate add. [" + key + "]"); + return; + } // 既に指定のパスが使われている LOG.error("Target duplicated. [" + key + "]"); + LOG.error("class:" + invokeTarget.getTargetClass().getName() + " method:" + invokeTarget.getTargetMethod().getName()); + LOG.error("class:" + exists.getTargetClass().getName() + " method:" + exists.getTargetMethod().getName()); throw new SystemException("Target duplicated. [" + key + "]"); } // 大文字/小文字は判定しない diff --git a/src/main/java/org/support/project/web/control/ApiControl.java b/src/main/java/org/support/project/web/control/ApiControl.java index 1fd6637..188dba8 100644 --- a/src/main/java/org/support/project/web/control/ApiControl.java +++ b/src/main/java/org/support/project/web/control/ApiControl.java @@ -1,8 +1,6 @@ package org.support.project.web.control; import org.support.project.common.config.Resources; -import org.support.project.common.util.StringUtils; -import org.support.project.web.bean.ApiParams; import org.support.project.web.bean.Msg; import org.support.project.web.boundary.Boundary; import org.support.project.web.common.HttpStatus; @@ -30,48 +28,4 @@ protected Boundary sendError(InvalidParamException e) { return this.sendError(HttpStatus.SC_400_BAD_REQUEST); } } - - public abstract Boundary getList(ApiParams params); - public abstract Boundary getSingle(String id); - public int maxLimit() { - return 50; - } - - protected ApiParams getApiParams() { - // 一覧取得 - int limit = 10; - int offset = 0; - String limitStr = getParam("limit"); - if (StringUtils.isInteger(limitStr)) { - limit = Integer.parseInt(limitStr); - } - if (limit > maxLimit()) { - limit = maxLimit(); - } - String offsetStr = getParam("offset"); - if (StringUtils.isInteger(offsetStr)) { - offset = Integer.parseInt(offsetStr); - } - ApiParams params = new ApiParams(); - params.setLimit(limit); - params.setOffset(offset); - return params; - } - - /** - * APIの基本的なGetのパターンを処理 - * 上の getList or getSingle が呼び出される - * @return - */ - protected Boundary get() { - String id = super.getPathString(""); - if (StringUtils.isEmpty(id)) { - ApiParams params = getApiParams(); - return getList(params); - } else { - // 1件取得 - return getSingle(id); - } - } - } diff --git a/src/main/java/org/support/project/web/control/Control.java b/src/main/java/org/support/project/web/control/Control.java index 047fa42..557015a 100644 --- a/src/main/java/org/support/project/web/control/Control.java +++ b/src/main/java/org/support/project/web/control/Control.java @@ -786,7 +786,27 @@ protected Map getParams() { } return map; } - + + /** + * 数値の情報を取得 + * @param param パラメータ名 + * @param defaultVal デフォルト + * @param maxVal 最大値 + * @return 数値 + */ + protected int getParamInt(String param, int defaultVal, int maxVal) { + int num = defaultVal; + String str = getParam(param); + if (StringUtils.isInteger(str)) { + num = Integer.parseInt(str); + } + if(num > maxVal) { + num = maxVal; + } + return num; + } + + /** * @return the sendEscapeHtml */ diff --git a/src/main/java/org/support/project/web/control/GetApiControl.java b/src/main/java/org/support/project/web/control/GetApiControl.java new file mode 100644 index 0000000..f3dc3f3 --- /dev/null +++ b/src/main/java/org/support/project/web/control/GetApiControl.java @@ -0,0 +1,52 @@ +package org.support.project.web.control; + +import org.support.project.common.util.StringUtils; +import org.support.project.web.bean.ApiParams; +import org.support.project.web.boundary.Boundary; + +public abstract class GetApiControl extends ApiControl { + + public abstract Boundary getList(ApiParams params); + public abstract Boundary getSingle(String id); + public int maxLimit() { + return 50; + } + + protected ApiParams getApiParams() { + // 一覧取得 + int limit = 10; + int offset = 0; + String limitStr = getParam("limit"); + if (StringUtils.isInteger(limitStr)) { + limit = Integer.parseInt(limitStr); + } + if (limit > maxLimit()) { + limit = maxLimit(); + } + String offsetStr = getParam("offset"); + if (StringUtils.isInteger(offsetStr)) { + offset = Integer.parseInt(offsetStr); + } + ApiParams params = new ApiParams(); + params.setLimit(limit); + params.setOffset(offset); + return params; + } + + /** + * APIの基本的なGetのパターンを処理 + * 上の getList or getSingle が呼び出される + * @return + */ + protected Boundary get() { + String id = super.getPathString(""); + if (StringUtils.isEmpty(id)) { + ApiParams params = getApiParams(); + return getList(params); + } else { + // 1件取得 + return getSingle(id); + } + } +} + diff --git a/src/main/java/org/support/project/web/dao/UsersDao.java b/src/main/java/org/support/project/web/dao/UsersDao.java index 82a35c7..db5c975 100644 --- a/src/main/java/org/support/project/web/dao/UsersDao.java +++ b/src/main/java/org/support/project/web/dao/UsersDao.java @@ -159,7 +159,7 @@ public List selectOnKeyword(int offset, int pageLimit, String keywo List params = new ArrayList(); sql.append("SELECT * FROM USERS WHERE DELETE_FLAG = 0 "); if (!StringUtils.isEmpty(keyword)) { - sql.append("AND USER_NAME LIKE ? "); + sql.append("AND USER_NAME ILIKE ? "); params.add("%" + keyword + "%"); } sql.append("ORDER BY USER_ID ASC Limit ? offset ?;"); diff --git a/src/main/java/org/support/project/web/logic/UserLogic.java b/src/main/java/org/support/project/web/logic/UserLogic.java index 49fab3c..6caaaf8 100644 --- a/src/main/java/org/support/project/web/logic/UserLogic.java +++ b/src/main/java/org/support/project/web/logic/UserLogic.java @@ -240,5 +240,20 @@ public void insertDefaultGroup(UsersEntity user) { userGroupsDao.insert(userGroupsEntity); } } + + /** + * ユーザの一覧を取得 + * @param keyword keyword + * @param offset offset + * @param limit limit + * @return ユーザの一覧 + */ + public List getUser(String keyword, int offset, int limit) { + List list = UsersDao.get().selectOnKeyword(offset, limit, keyword); + for (UsersEntity usersEntity : list) { + usersEntity.setPassword(null); // パスワードは返さない + } + return list; + } } diff --git a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectAdminOnKeyword.sql b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectAdminOnKeyword.sql index 2d4f874..7ca05c4 100644 --- a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectAdminOnKeyword.sql +++ b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectAdminOnKeyword.sql @@ -5,7 +5,7 @@ SELECT WHERE GROUPS.DELETE_FLAG = 0 AND - GROUPS.GROUP_NAME LIKE '%' || ? || '%' + GROUPS.GROUP_NAME ILIKE '%' || ? || '%' GROUP BY GROUPS.GROUP_ID ORDER BY diff --git a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectMyGroupOnKeyword.sql b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectMyGroupOnKeyword.sql index 1368828..44aa675 100644 --- a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectMyGroupOnKeyword.sql +++ b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectMyGroupOnKeyword.sql @@ -3,7 +3,7 @@ SELECT FROM GROUPS WHERE - GROUPS.GROUP_NAME LIKE '%' || ? || '%' + GROUPS.GROUP_NAME ILIKE '%' || ? || '%' AND GROUPS.DELETE_FLAG = 0 AND diff --git a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectOnKeyword.sql b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectOnKeyword.sql index 9cfb6cc..c6e9c5d 100644 --- a/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectOnKeyword.sql +++ b/src/main/resources/org/support/project/web/dao/sql/GroupsDao/GroupsDao_selectOnKeyword.sql @@ -4,7 +4,7 @@ SELECT GROUPS WHERE GROUPS.DELETE_FLAG = 0 - AND GROUPS.GROUP_NAME LIKE '%' || ? || '%' + AND GROUPS.GROUP_NAME ILIKE '%' || ? || '%' AND ( EXISTS ( SELECT diff --git a/src/test/java/org/support/project/web/config/AppconfigTest.java b/src/test/java/org/support/project/web/config/AppconfigTest.java index 44159a4..e2118be 100644 --- a/src/test/java/org/support/project/web/config/AppconfigTest.java +++ b/src/test/java/org/support/project/web/config/AppconfigTest.java @@ -10,7 +10,6 @@ public class AppconfigTest { - @Test public void test() { assertEquals("web", AppConfig.get().getSystemName()); From 2717185664c1deac4cb8235ec0d8389fbc8f0708 Mon Sep 17 00:00:00 2001 From: Koda Date: Wed, 29 Nov 2017 21:41:01 +0900 Subject: [PATCH 2/6] Fix check a csrf token --- .../support/project/web/bean/CSRFTokens.java | 46 +++++++++++++------ .../web/logic/HttpRequestCheckLogic.java | 8 ++-- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/support/project/web/bean/CSRFTokens.java b/src/main/java/org/support/project/web/bean/CSRFTokens.java index 216b283..78b98f3 100644 --- a/src/main/java/org/support/project/web/bean/CSRFTokens.java +++ b/src/main/java/org/support/project/web/bean/CSRFTokens.java @@ -2,8 +2,8 @@ import java.io.Serializable; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedHashMap; import org.support.project.common.serialize.Serialize; import org.support.project.common.serialize.SerializerValue; @@ -14,33 +14,48 @@ public class CSRFTokens implements Serializable { * シリアルバージョン */ private static final long serialVersionUID = 1L; - - private List tokens = new ArrayList<>(); - + + private LinkedHashMap tokens = new LinkedHashMap<>(); + /** * 指定のキーに対するTokenを発行する - * @param key key + * + * @param key key * @throws NoSuchAlgorithmException NoSuchAlgorithmException */ public String addToken(String key) throws NoSuchAlgorithmException { + if (tokens.containsKey(key)) { + CSRFToken token = tokens.get(key); + return token.getToken(); + } if (tokens.size() > 20) { - tokens.remove(0); + Iterator iterator = tokens.keySet().iterator(); + while (iterator.hasNext()) { + String string = (String) iterator.next(); + tokens.remove(string); // 初めの1件を削除(古いもの) + break; + } } CSRFToken token = CSRFToken.create(key); - tokens.add(token); + tokens.put(key, token); return token.getToken(); } - + /** * トークンが正しい値かチェックする + * * @param key key * @param reqTokens CSRFTokens * @return チェック結果 */ public boolean checkToken(String key, CSRFTokens reqTokens) { - for (CSRFToken csrfToken : tokens) { + Iterator iterator = tokens.values().iterator(); + while (iterator.hasNext()) { + CSRFToken csrfToken = (CSRFToken) iterator.next(); if (csrfToken.getKey().equals(key)) { - for (CSRFToken reqToken : reqTokens.tokens) { + Iterator iterator2 = reqTokens.tokens.values().iterator(); + while (iterator2.hasNext()) { + CSRFToken reqToken = (CSRFToken) iterator2.next(); if (reqToken.getKey().equals(key) && csrfToken.getToken().equals(reqToken.getToken())) { return true; } @@ -49,14 +64,17 @@ public boolean checkToken(String key, CSRFTokens reqTokens) { } return false; } - + /** * リクエストのHiddenトークンが正しい値かチェックする + * * @param key key * @return チェック結果 */ public boolean checkToken(String key) { - for (CSRFToken csrfToken : tokens) { + Iterator iterator = tokens.values().iterator(); + while (iterator.hasNext()) { + CSRFToken csrfToken = (CSRFToken) iterator.next(); if (csrfToken.getToken().equals(key)) { // 保持されているTokenのリストの中に存在すればOK return true; @@ -64,5 +82,5 @@ public boolean checkToken(String key) { } return false; } - + } diff --git a/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java b/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java index 3d55537..7a58d07 100644 --- a/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java +++ b/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java @@ -171,7 +171,8 @@ public void setCSRFTocken(InvokeTarget invokeTarget, HttpServletRequest request, tokens = new CSRFTokens(); session.setAttribute(CSRF_TOKENS, tokens); } - tokens.addToken(tokenkey); + String result = tokens.addToken(tokenkey); + LOG.info("Add token to CSRF_TOKENS. key:" + tokenkey + " token:" + result); try { HttpUtil.setCookie(request, response, CSRF_TOKENS, SerializeUtils.objectToBase64(tokens)); } catch (SerializeException e) { @@ -184,9 +185,7 @@ public void setCSRFTocken(InvokeTarget invokeTarget, HttpServletRequest request, session.setAttribute(CSRF_REQIDS, reqids); } String reqid = reqids.addToken(tokenkey); - if (LOG.isDebugEnabled()) { - LOG.debug("Req Token : " + reqid); - } + LOG.info("Add token to CSRF_REQIDS. key:" + tokenkey + " token:" + reqid); request.setAttribute(REQ_ID_KEY, reqid); } } @@ -230,6 +229,7 @@ public boolean checkCSRF(InvokeTarget invokeTarget, HttpServletRequest request) } if (isCheckReqToken(invokeTarget)) { + // HiddenパラメータにRequestTokenがセットされているかチェックする場合 String reqId = request.getParameter(REQ_ID_KEY); CSRFTokens reqids = (CSRFTokens) session.getAttribute(CSRF_REQIDS); if (reqids == null) { From 86fed123dac7aa17109c851dbbc2141aff9c6de0 Mon Sep 17 00:00:00 2001 From: Koda Date: Wed, 29 Nov 2017 23:45:24 +0900 Subject: [PATCH 3/6] Fix log level --- .../support/project/web/logic/HttpRequestCheckLogic.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java b/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java index 7a58d07..ea9c74e 100644 --- a/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java +++ b/src/main/java/org/support/project/web/logic/HttpRequestCheckLogic.java @@ -172,7 +172,9 @@ public void setCSRFTocken(InvokeTarget invokeTarget, HttpServletRequest request, session.setAttribute(CSRF_TOKENS, tokens); } String result = tokens.addToken(tokenkey); - LOG.info("Add token to CSRF_TOKENS. key:" + tokenkey + " token:" + result); + if (LOG.isDebugEnabled()) { + LOG.debug("Add token to CSRF_TOKENS. key:" + tokenkey + " token:" + result); + } try { HttpUtil.setCookie(request, response, CSRF_TOKENS, SerializeUtils.objectToBase64(tokens)); } catch (SerializeException e) { @@ -185,7 +187,9 @@ public void setCSRFTocken(InvokeTarget invokeTarget, HttpServletRequest request, session.setAttribute(CSRF_REQIDS, reqids); } String reqid = reqids.addToken(tokenkey); - LOG.info("Add token to CSRF_REQIDS. key:" + tokenkey + " token:" + reqid); + if (LOG.isDebugEnabled()) { + LOG.debug("Add token to CSRF_REQIDS. key:" + tokenkey + " token:" + reqid); + } request.setAttribute(REQ_ID_KEY, reqid); } } From ebf858a52c063002937779c72cb4b74a254f3e39 Mon Sep 17 00:00:00 2001 From: Koda Date: Sat, 2 Dec 2017 08:23:52 +0900 Subject: [PATCH 4/6] allow a attribute "transition" at sanitize --- src/main/java/org/support/project/web/logic/SanitizingLogic.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/support/project/web/logic/SanitizingLogic.java b/src/main/java/org/support/project/web/logic/SanitizingLogic.java index 37fd372..31ec685 100644 --- a/src/main/java/org/support/project/web/logic/SanitizingLogic.java +++ b/src/main/java/org/support/project/web/logic/SanitizingLogic.java @@ -85,6 +85,7 @@ public boolean apply(String s) { "var") .allowAttributes("id").matching(HTML_ID).globally() .allowAttributes("slide").matching(NUMBER).globally() + .allowAttributes("transition").matching(HTML_CLASS).globally() .allowAttributes("class").matching(HTML_CLASS).globally() .allowAttributes("lang").matching(Pattern.compile("[a-zA-Z]{2,20}")).globally() .allowAttributes("title").matching(HTML_TITLE).globally() From 8b5ff2a1ee21f1d60fbad65196b41d3d1eb9cf59 Mon Sep 17 00:00:00 2001 From: Koda Date: Sat, 2 Dec 2017 11:33:15 +0900 Subject: [PATCH 5/6] allow a attribute "centerd" at sanitize --- src/main/java/org/support/project/web/logic/SanitizingLogic.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/support/project/web/logic/SanitizingLogic.java b/src/main/java/org/support/project/web/logic/SanitizingLogic.java index 31ec685..bd9df3b 100644 --- a/src/main/java/org/support/project/web/logic/SanitizingLogic.java +++ b/src/main/java/org/support/project/web/logic/SanitizingLogic.java @@ -86,6 +86,7 @@ public boolean apply(String s) { .allowAttributes("id").matching(HTML_ID).globally() .allowAttributes("slide").matching(NUMBER).globally() .allowAttributes("transition").matching(HTML_CLASS).globally() + .allowAttributes("centered").matching(HTML_CLASS).globally() .allowAttributes("class").matching(HTML_CLASS).globally() .allowAttributes("lang").matching(Pattern.compile("[a-zA-Z]{2,20}")).globally() .allowAttributes("title").matching(HTML_TITLE).globally() From b265aefcd5c67f87e2d2f0e9a4719042585d80e6 Mon Sep 17 00:00:00 2001 From: Koda Date: Mon, 8 Jan 2018 12:56:33 +0900 Subject: [PATCH 6/6] Release v1.12.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f93329e..48efbd7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.support-project web - 1.12.0-SNAPSHOT + 1.12.0 jar web @@ -59,7 +59,7 @@ org.support-project common - 1.12.0-SNAPSHOT + 1.12.0