Browse Source

:zap: 修复mybatis-plus排序字段的sql注入问题,优化saber代码生成模板

smallchill 5 years ago
parent
commit
eb9ddd1b7e

+ 20 - 17
blade-core-develop/src/main/resources/templates/saber/crud.vue.vm

@@ -3,12 +3,12 @@
     <avue-crud :option="option"
                :data="data"
                :page="page"
-               @row-del="rowDel"
-               v-model="form"
                :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
                @row-update="rowUpdate"
                @row-save="rowSave"
-               :before-open="beforeOpen"
+               @row-del="rowDel"
                @search-change="searchChange"
                @search-reset="searchReset"
                @selection-change="selectionChange"
@@ -36,6 +36,7 @@
     data() {
       return {
         form: {},
+        query: {},
         page: {
           pageSize: 10,
           currentPage: 1,
@@ -71,10 +72,10 @@
       ...mapGetters(["permission"]),
       permissionList() {
         return {
-          addBtn: this.vaildData(this.permission.$!{cfg.entityKey}_add),
-          viewBtn: this.vaildData(this.permission.$!{cfg.entityKey}_view),
-          delBtn: this.vaildData(this.permission.$!{cfg.entityKey}_delete),
-          editBtn: this.vaildData(this.permission.$!{cfg.entityKey}_edit)
+          addBtn: this.vaildData(this.permission.$!{cfg.entityKey}_add, false),
+          viewBtn: this.vaildData(this.permission.$!{cfg.entityKey}_view, false),
+          delBtn: this.vaildData(this.permission.$!{cfg.entityKey}_delete, false),
+          editBtn: this.vaildData(this.permission.$!{cfg.entityKey}_edit, false)
         };
       },
       ids() {
@@ -129,15 +130,6 @@
             });
           });
       },
-      searchReset() {
-        this.onLoad(this.page);
-      },
-      searchChange(params) {
-        this.onLoad(this.page, params);
-      },
-      selectionChange(list) {
-        this.selectionList = list;
-      },
       handleDelete() {
         if (this.selectionList.length === 0) {
           this.$message.warning("请选择至少一条数据");
@@ -168,6 +160,17 @@
         }
         done();
       },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params) {
+        this.query = params;
+        this.onLoad(this.page, params);
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
       currentChange(currentPage){
         this.page.currentPage = currentPage;
       },
@@ -175,7 +178,7 @@
         this.page.pageSize = pageSize;
       },
       onLoad(page, params = {}) {
-        getList(page.currentPage, page.pageSize, params).then(res => {
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
           const data = res.data.data;
           this.page.total = data.total;
           this.data = data.records;

+ 3 - 10
blade-core-mybatis/src/main/java/org/springblade/core/mp/support/Condition.java

@@ -20,7 +20,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.StringUtil;
 
 import java.util.Map;
 
@@ -39,8 +38,8 @@ public class Condition {
 	 */
 	public static <T> IPage<T> getPage(Query query) {
 		Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
-		page.setAsc(Func.toStrArray(query.getAscs()));
-		page.setDesc(Func.toStrArray(query.getDescs()));
+		page.setAsc(Func.toStrArray(SqlKeyword.filter(query.getAscs())));
+		page.setDesc(Func.toStrArray(SqlKeyword.filter(query.getDescs())));
 		return page;
 	}
 
@@ -68,13 +67,7 @@ public class Condition {
 		query.remove("size");
 		QueryWrapper<T> qw = new QueryWrapper<>();
 		qw.setEntity(BeanUtil.newInstance(clazz));
-		if (Func.isNotEmpty(query)) {
-			query.forEach((k, v) -> {
-				if (Func.isNotEmpty(v)) {
-					qw.like(StringUtil.humpToUnderline(k), v);
-				}
-			});
-		}
+		SqlKeyword.buildCondition(query, qw);
 		return qw;
 	}
 

+ 110 - 0
blade-core-mybatis/src/main/java/org/springblade/core/mp/support/SqlKeyword.java

@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.gnu.org/licenses/lgpl.html
+ * <p>
+ * 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 org.springblade.core.mp.support;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringPool;
+import org.springblade.core.tool.utils.StringUtil;
+
+import java.util.Map;
+
+/**
+ * 定义常用的 sql关键字
+ *
+ * @author Chill
+ */
+public class SqlKeyword {
+	private final static String SQL_REGEX = "'|%|--|insert|delete|update|select|count|group|union|create|drop|truncate|alter|grant|execute|exec|xp_cmdshell|call|declare|sql";
+
+	private static final String EQUAL = "_equal";
+	private static final String NOT_EQUAL = "_notequal";
+	private static final String LIKE = "_like";
+	private static final String NOT_LIKE = "_notlike";
+	private static final String GT = "_gt";
+	private static final String LT = "_lt";
+	private static final String DATE_GT = "_dategt";
+	private static final String DATE_EQUAL = "_dateequal";
+	private static final String DATE_LT = "_datelt";
+	private static final String IS_NULL = "_null";
+	private static final String NOT_NULL = "_notnull";
+	private static final String IGNORE = "_ignore";
+
+	/**
+	 * 条件构造器
+	 *
+	 * @param query 查询字段
+	 * @param qw    查询包装类
+	 */
+	public static void buildCondition(Map<String, Object> query, QueryWrapper<?> qw) {
+		if (Func.isEmpty(query)) {
+			return;
+		}
+		query.forEach((k, v) -> {
+			if (Func.hasEmpty(k, v) || k.endsWith(IGNORE)) {
+				return;
+			}
+			if (k.endsWith(EQUAL)) {
+				qw.eq(getColumn(k, EQUAL), v);
+			} else if (k.endsWith(NOT_EQUAL)) {
+				qw.ne(getColumn(k, NOT_EQUAL), v);
+			} else if (k.endsWith(NOT_LIKE)) {
+				qw.notLike(getColumn(k, NOT_LIKE), v);
+			} else if (k.endsWith(GT)) {
+				qw.gt(getColumn(k, GT), v);
+			} else if (k.endsWith(LT)) {
+				qw.lt(getColumn(k, LT), v);
+			} else if (k.endsWith(DATE_GT)) {
+				qw.gt(getColumn(k, DATE_GT), v);
+			} else if (k.endsWith(DATE_EQUAL)) {
+				qw.eq(getColumn(k, DATE_EQUAL), v);
+			} else if (k.endsWith(DATE_LT)) {
+				qw.lt(getColumn(k, DATE_LT), v);
+			} else if (k.endsWith(IS_NULL)) {
+				qw.isNull(getColumn(k, IS_NULL));
+			} else if (k.endsWith(NOT_NULL)) {
+				qw.isNotNull(getColumn(k, NOT_NULL));
+			} else {
+				qw.like(getColumn(k, LIKE), v);
+			}
+		});
+	}
+
+	/**
+	 * 获取数据库字段
+	 *
+	 * @param column  字段名
+	 * @param keyword 关键字
+	 * @return
+	 */
+	private static String getColumn(String column, String keyword) {
+		return StringUtil.humpToUnderline(StringUtil.removeSuffix(column, keyword));
+	}
+
+	/**
+	 * 把SQL关键字替换为空字符串
+	 *
+	 * @param param 关键字
+	 * @return string
+	 */
+	public static String filter(String param) {
+		if (param == null) {
+			return null;
+		}
+		return param.replaceAll("(?i)" + SQL_REGEX, StringPool.EMPTY);
+	}
+
+}