若依(RuoYi)中创建表报错问题
该请求是只能出现创建表的sql语句,所以不要出现drop table if exists table;等语句,这样是会报错的。(之前被这个问题坑过)
解决办法:
只写入创建表的语句,例如:
create table sys_product (
product_id bigint(20) not null auto_increment comment '产品id',
parent_id bigint(20) default 0 comment '父产品id',
product_name varchar(30) default '' comment '产品名称',
order_num int(4) default 0 comment '显示顺序',
status char(1) default '0' comment '产品状态(0正常 1停用)',
primary key (product_id)
) engine=innodb auto_increment=1 comment = '产品表';
原因:
查看请求处理代码如下,主要分为3部分:
@PostMapping("/createTable")
@ResponseBody
public AjaxResult create(String sql)
{
try
{
//1.判断是否为创建表的语句
SqlUtil.filterKeyword(sql);
//2.进行创建表
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
List<String> tableNames = new ArrayList<>();
for (SQLStatement sqlStatement : sqlStatements)
{
if (sqlStatement instanceof MySqlCreateTableStatement)
{
MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
if (genTableService.createTable(createTableStatement.toString()))
{
String tableName = createTableStatement.getTableName().replaceAll("`", "");
tableNames.add(tableName);
}
}
}
//3.在gen_table和gen_table_column表中记录关于创建的表的信息及字段信息
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
genTableService.importGenTable(tableList, operName);
return AjaxResult.success();
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
return AjaxResult.error("创建表结构异常[" + e.getMessage() + "]");
}
}
接下来一步步分析
SqlUtil.filterKeyword(sql);
这个语句就是用来分析是否为创建表的语句,前面报错的原因就是因为它
它里面的主要内容是这样的
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
public static void filterKeyword(String value)
{
if (StringUtils.isEmpty(value))
{
return;
}
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
{
throw new UtilException("参数存在SQL注入风险");
}
}
}
其实就是很简单的将所有sql关键字写入SQL_REGEX变量中,然后按照“|”字符切割出这些关键字。在判断sql语句里面是否有这些关键字,若有则报错