若依(ruoyi)创建表的请求源码分析

若依(ruoyi)创建表的请求源码分析

请求路径 /tool/gen/createTable

该请求是只能出现创建表的sql语句,所以不要出现drop table if exists table;等语句,这样是会报错的。(之前被这个问题坑过)
在这里插入图片描述
该请求处理代码如下,主要分为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语句里面是否有这些关键字,若有则报错

List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
...
    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);
            }
        }
    }

这里就是用阿里的Druid包,进行处理,判断是否为mysql的创建表语句,若是则调用genTableService.createTable进行建表

List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
            String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
            genTableService.importGenTable(tableList, operName);

这一步很巧妙,它是操作mysql中information_schema数据库中TABLES和COLUMNS表获取出关于所要创建的表的信息。这样就不用在请求的时候携带关于创建时间等请求参数、以及在解析sql得到表名、字段名、字段类型、约束等操作,节省了很多代码。(information_schema数据库是mysql自带的,保存着关于MySQL服务器所维护的所有其他数据库的信息)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值