diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/RequestMethod.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/RequestMethod.java new file mode 100644 index 00000000..de297023 --- /dev/null +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/RequestMethod.java @@ -0,0 +1,23 @@ +/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.*/ + +package zuo.biao.apijson; + +/**请求方法,对应org.springframework.web.bind.annotation.RequestMethod,多出一个POST_GET方法 + * @author Lemon + */ +public enum RequestMethod { + + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, POST_GET +} diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/Table.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/Table.java index bfce4778..598e7d32 100644 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/Table.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/Table.java @@ -3,6 +3,7 @@ package zuo.biao.apijson; public class Table { public static final String ID = "id"; + public static final String USER_ID = "userId"; public static final String NAME = "name"; public static final String SEX = "sex"; public static final String PHONE = "phone"; diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/ClientTest.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/ClientTest.java index f49b587f..0dce815d 100755 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/ClientTest.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/ClientTest.java @@ -14,7 +14,7 @@ limitations under the License.*/ package zuo.biao.apijson.server; -import org.springframework.web.bind.annotation.RequestMethod; +import zuo.biao.apijson.RequestMethod; /**mock test of client * @author Lemon diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/Controller.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/Controller.java index 26f37a82..c6ed5fda 100755 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/Controller.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/Controller.java @@ -29,12 +29,12 @@ public class Controller { @RequestMapping("get/{request}") public String get(@PathVariable String request) { - return new RequestParser(RequestMethod.GET).parse(request); + return new RequestParser(zuo.biao.apijson.RequestMethod.GET).parse(request); } @RequestMapping(value="post", method = RequestMethod.POST) public String post(@RequestBody String request) { - return new RequestParser(RequestMethod.POST).parse(request); + return new RequestParser(zuo.biao.apijson.RequestMethod.POST).parse(request); } /**用POST方法GET数据,request和response都非明文,浏览器看不到,用于对安全性要求高的GET请求 @@ -43,7 +43,6 @@ public class Controller { */ @RequestMapping(value="post_get", method = RequestMethod.POST) public String post_get(@RequestBody String request) { - return new RequestParser(RequestMethod.GET).parse(request); } /**以下接口继续用POST接口是为了客户端方便,只需要做get,post请求。也可以改用实际对应的方法。 @@ -51,12 +50,12 @@ public class Controller { */ @RequestMapping(value="delete", method = RequestMethod.POST) public String delete(@RequestBody String request) { - return new RequestParser(RequestMethod.DELETE).parse(request); + return new RequestParser(zuo.biao.apijson.RequestMethod.DELETE).parse(request); } @RequestMapping(value="put", method = RequestMethod.POST) public String put(@RequestBody String request) { - return new RequestParser(RequestMethod.PUT).parse(request); + return new RequestParser(zuo.biao.apijson.RequestMethod.PUT).parse(request); } } diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/QueryConfig.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/QueryConfig.java index 3f6b0346..14c950ee 100755 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/QueryConfig.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/QueryConfig.java @@ -19,11 +19,10 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import org.springframework.web.bind.annotation.RequestMethod; - import com.alibaba.fastjson.JSONObject; import zuo.biao.apijson.JSON; +import zuo.biao.apijson.RequestMethod; import zuo.biao.apijson.StringUtil; import zuo.biao.apijson.Table; diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/RequestParser.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/RequestParser.java index 8ee6eefe..042ada36 100755 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/RequestParser.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/RequestParser.java @@ -24,11 +24,10 @@ import java.util.Map; import java.util.Set; import java.util.regex.Pattern; -import org.springframework.web.bind.annotation.RequestMethod; - import com.alibaba.fastjson.JSONObject; import zuo.biao.apijson.JSON; +import zuo.biao.apijson.RequestMethod; import zuo.biao.apijson.StringUtil; import zuo.biao.apijson.Table; import zuo.biao.apijson.server.sql.AccessVerifier; @@ -80,7 +79,7 @@ public class RequestParser { return newErrorResult(e); } System.out.println("\n\n\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n " + TAG + requestMethod.name() - + "/parseResponse request = " + request); + + "/parseResponse request = " + request); relationMap = new HashMap(); parseRelation = false; @@ -106,7 +105,7 @@ public class RequestParser { requestObject = AccessVerifier.removeAccessInfo(requestObject); - if (isGetMethod(requestMethod)) { + if (isGetMethod(requestMethod) || requestMethod == RequestMethod.POST_GET) { requestObject = error == null ? extendSuccessResult(requestObject) : extendResult(requestObject, 206, "未完成全部请求:\n" + error.getMessage()); } @@ -706,7 +705,7 @@ public class RequestParser { */ private synchronized JSONObject getSQLObject(QueryConfig config) throws Exception { System.out.println("getSQLObject config = " + JSON.toJSONString(config)); - AccessVerifier.verify(requestMethod, requestObject, config == null ? null : config.getTable()); + AccessVerifier.verify(requestObject, config); return QueryHelper.getInstance().select(config);//QueryHelper2.getInstance().select(config);// } @@ -721,12 +720,12 @@ public class RequestParser { private static final Pattern bigAlphaPattern = Pattern.compile("[A-Z]"); + private static final Pattern namePattern = Pattern.compile("^[0-9a-zA-Z_]+$");//已用55个中英字符测试通过 public static boolean isTableKey(String key) { - key = StringUtil.getString(key); - - return StringUtil.isNotEmpty(key, false) && isArrayKey(key) == false - && bigAlphaPattern.matcher(key.substring(0, 1)).matches(); + return StringUtil.isNotEmpty(key, false) + && bigAlphaPattern.matcher(key.substring(0, 1)).matches() + && namePattern.matcher(key.substring(1)).matches(); } public static boolean isArrayKey(String key) { return key != null && key.endsWith("[]"); diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/AccessVerifier.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/AccessVerifier.java index e74f729e..087b6df3 100644 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/AccessVerifier.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/AccessVerifier.java @@ -2,11 +2,11 @@ package zuo.biao.apijson.server.sql; import java.rmi.AccessException; -import org.springframework.web.bind.annotation.RequestMethod; - import com.alibaba.fastjson.JSONObject; +import zuo.biao.apijson.RequestMethod; import zuo.biao.apijson.StringUtil; +import zuo.biao.apijson.server.QueryConfig; /**权限验证类 * @author Lemon @@ -21,39 +21,65 @@ public class AccessVerifier { public static final String KEY_LOGIN_PASSWORD = "loginPassword"; public static final String KEY_PAY_PASSWORD = "payPassword"; - // public static final String[] LOGIN_ACCESS_TABLE_NAMES = {"Work", "Comment"}; - public static final String[] PAY_ACCESS_TABLE_NAMES = {"Wallet"}; + public static final String[] LOGIN_ACCESS_TABLE_NAMES = {"Wallet"}; + public static final String[] PAY_ACCESS_TABLE_NAMES = {}; /**验证权限是否通过 - * @param method * @param request - * @param tableName + * @param config * @return + * @throws Exception */ - public static boolean verify(RequestMethod method, JSONObject request, String tableName) throws AccessException { - return verify(method, request, getAccessId(tableName)); - } - - - /**验证权限是否通过 - * @param method - * @param request - * @param accessId 可以直接在代码里写ACCESS_LOGIN等,或者建一个Access表,包括id和需要改权限的table的tableName列表 - * @return - * @throws AccessException - */ - public static boolean verify(RequestMethod method, JSONObject request, int accessId) throws AccessException { - if (accessId < 0 || request == null) { + public static boolean verify(JSONObject request, QueryConfig config) throws Exception { + String table = config == null ? null : config.getTable(); + if (table == null) { return true; } + if (request == null) { + return false; + } + long currentUserId = request.getLongValue(KEY_CURRENT_USER_ID); + + switch (config.getMethod()) { + case GET: + case POST_GET: + if ("Wallet".equals(table) || "Password".equals(table)) { + verifyUserId(currentUserId, config); + } + break; + case POST: + case PUT: + case PATCH: + case DELETE: + verifyUserId(currentUserId, config); + break; + default: + break; + } + + return verifyAccess(request, table, config.getMethod(), currentUserId); + } + + /** + * @param request + * @param table + * @param method + * @param currentUserId + * @return + * @throws AccessException + */ + private static boolean verifyAccess(JSONObject request, String table, RequestMethod method, long currentUserId) throws AccessException { + int accessId = getAccessId(method, table); + if (accessId < 0) { + return true; + } if (currentUserId <= 0) { System.out.println(TAG + "verify accessId = " + accessId + " >> currentUserId <= 0, currentUserId = " + currentUserId); throw new AccessException("请设置"+ KEY_CURRENT_USER_ID + "和对应的password!"); } String password; - switch (accessId) { case ACCESS_LOGIN: password = StringUtil.getString(request.getString(KEY_LOGIN_PASSWORD)); @@ -63,6 +89,7 @@ public class AccessVerifier { + " currentUserId = " + currentUserId + ", loginPassword = " + password); throw new AccessException(KEY_CURRENT_USER_ID + "或" + KEY_LOGIN_PASSWORD + "错误!"); } + break; case ACCESS_PAY: password = StringUtil.getString(request.getString(KEY_PAY_PASSWORD)); if (password.equals(StringUtil.getString(getPayPassword(currentUserId))) == false) { @@ -71,9 +98,36 @@ public class AccessVerifier { + " currentUserId = " + currentUserId + ", payPassword = " + password); throw new AccessException(KEY_CURRENT_USER_ID + "或" + KEY_PAY_PASSWORD + "错误!"); } - default: - return true; + break; } + return true; + } + /** + * @param currentUserId + * @param config + * @return + * @throws Exception + */ + private static boolean verifyUserId(long currentUserId, QueryConfig config) throws Exception { + // if (currentUserId <= 0 || config == null) { + // return true; + // } + // Map where = config.getWhere(); + // long userId = 0; + // String table = StringUtil.getString(config.getTable()); + // if (where != null) { + // try { + // String key = "User".equals(table) ? Table.ID : Table.USER_ID; + // userId = (long) where.get(key); + // } catch (Exception e) { + // // TODO: handle exception + // } + // } + // if (userId != currentUserId) { + // throw new IllegalArgumentException(table + "的userId和currentUserId不一致!"); + // } + + return true; } @@ -82,17 +136,17 @@ public class AccessVerifier { * @param tableName * @return */ - public static int getAccessId(String tableName) { - if (StringUtil.isNotEmpty(tableName, true) == false) { + public static int getAccessId(RequestMethod method, String table) { + if (StringUtil.isNotEmpty(table, true) == false) { return -1; } - // for (int i = 0; i < LOGIN_ACCESS_TABLE_NAMES.length; i++) { - // if (tableName.equals(LOGIN_ACCESS_TABLE_NAMES[i])) { - // return ACCESS_LOGIN; - // } - // } + for (int i = 0; i < LOGIN_ACCESS_TABLE_NAMES.length; i++) { + if (table.equals(LOGIN_ACCESS_TABLE_NAMES[i])) { + return ACCESS_LOGIN; + } + } for (int i = 0; i < PAY_ACCESS_TABLE_NAMES.length; i++) { - if (tableName.equals(PAY_ACCESS_TABLE_NAMES[i])) { + if (table.equals(PAY_ACCESS_TABLE_NAMES[i])) { return ACCESS_PAY; } } @@ -105,7 +159,7 @@ public class AccessVerifier { */ public static String getLoginPassword(long userId) { // TODO 查询并返回对应userId的登录密码 - return "123456";//仅测试用 + return "apijson123";//仅测试用 } /**获取支付密码 @@ -130,4 +184,11 @@ public class AccessVerifier { return requestObject; } + + // public static class Access { + // public static class Get { + // public static final String[] LOGIN_ACCESS_TABLE_NAMES = {"Wallet"}; + // } + // } + } diff --git a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/QueryHelper.java b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/QueryHelper.java index f28d0045..dfe41867 100755 --- a/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/QueryHelper.java +++ b/APIJSON(Server)/APIJSON(Eclipse_JEE)/src/main/java/zuo/biao/apijson/server/sql/QueryHelper.java @@ -25,6 +25,7 @@ import java.util.List; import com.alibaba.fastjson.JSONObject; +import zuo.biao.apijson.RequestMethod; import zuo.biao.apijson.StringUtil; import zuo.biao.apijson.Table; import zuo.biao.apijson.server.QueryConfig; @@ -38,6 +39,7 @@ public class QueryHelper { private static final String YOUR_MYSQL_URL = "jdbc:mysql://localhost:3306/";//TODO edit to an available one private static final String YOUR_MYSQL_SCHEMA = "sys";//TODO edit to an available one + private static final String YOUR_MYSQL_SCHEMA_SECURITY = "security";//TODO edit to an available one private static final String YOUR_MYSQL_ACCOUNT = "root";//TODO edit to an available one private static final String YOUR_MYSQL_PASSWORD = "apijson";//TODO edit to an available one @@ -54,10 +56,16 @@ public class QueryHelper { } public Connection getConnection() throws Exception { + return getConnection(null); + } + public Connection getConnection(String schema) throws Exception { + if (schema == null) { + schema = YOUR_MYSQL_SCHEMA; + } //调用Class.forName()方法加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); System.out.println(TAG + "成功加载MySQL驱动!"); - return DriverManager.getConnection(YOUR_MYSQL_URL + YOUR_MYSQL_SCHEMA, YOUR_MYSQL_ACCOUNT, YOUR_MYSQL_PASSWORD); + return DriverManager.getConnection(YOUR_MYSQL_URL + schema, YOUR_MYSQL_ACCOUNT, YOUR_MYSQL_PASSWORD); } @@ -90,7 +98,7 @@ public class QueryHelper { if (connection == null || connection.isClosed()) { System.out.println(TAG + "select connection " + (connection == null ? " = null" : ("isClosed = " + connection.isClosed()))) ; - connection = getConnection(); + connection = getConnection(getSchema(config.getMethod())); statement = connection.createStatement(); //创建Statement对象 metaData = connection.getMetaData(); } @@ -105,18 +113,23 @@ public class QueryHelper { JSONObject object = null;//new JSONObject(true); ResultSet rs = null; switch (config.getMethod()) { + case GET: + case POST_GET: + rs = statement.executeQuery(sql); + break; case POST: case PUT: + case PATCH: case DELETE: - int updateCount = statement.executeUpdate(sql);//创建数据对象 + int updateCount = statement.executeUpdate(sql); JSONObject result = RequestParser.newResult(updateCount > 0 ? 200 : 404 , updateCount > 0 ? "success" : "可能对象不存在!"); result.put(Table.ID, config.getId()); return result; - default: - rs = statement.executeQuery(sql);//创建数据对象 - break; + default://HEAD, OPTIONS, TRACE等 + System.out.println(TAG + "select sql = " + sql + " ; method = " + config.getMethod() + " >> return null;"); + return null; } @@ -169,29 +182,55 @@ public class QueryHelper { return list.toArray(new String[]{}); } + /** + * @param method + * @return + */ + public static String getSchema(RequestMethod method) { + return method == RequestMethod.POST_GET ? YOUR_MYSQL_SCHEMA_SECURITY : YOUR_MYSQL_SCHEMA; + } + /** * @param table * @return * @throws Exception */ public int getCount(String table) throws Exception { + return getCount(table, RequestMethod.GET); + } + /** + * @param table + * @param method + * @return + * @throws Exception + */ + public int getCount(String table, RequestMethod method) throws Exception { + return getCount(table, getSchema(method)); + } + /** + * @param table + * @param schema + * @return + * @throws Exception + */ + public int getCount(String table, String schema) throws Exception { if (connection == null || connection.isClosed()) { System.out.println(TAG + "getCount connection " + (connection == null ? " = null" : ("isClosed = " + connection.isClosed()))) ; - connection = getConnection(); + connection = getConnection(schema); statement = connection.createStatement(); //创建Statement对象 metaData = connection.getMetaData(); } ResultSet rs = statement.executeQuery("SELECT Count(*) FROM " + table);//创建数据对象 - + int count = 0; if (rs.next()) { count = rs.getInt(1); } System.out.println(TAG + "getCount count = " + count) ; - + rs.close(); - + return count; }