mybatis执行动态sql如何防止sql注入?

sql的表名和字段都是不确定的 所以只能执行sql

<insert id="insertSql" parameterType="String">
        ${sql}
    </insert>

像这种 有没有办法检测这个拼接好的sql字符串有问题

阅读 3.6k
5 个回答

既然用mybatis了。 为啥还直接传进来整个sql。

用白名单, 只允许特定的几条sql, 或者几个变量的值. 没别的办法.

我觉得要直接在mapper文件里(用了$)处理sql注入问题是不可能的
mybatis已经明确指出, 使用#能够防止sql注入, $则不能, 一定要用也没办法呀
那么既然使用 $ 就应该要确保穿进去的sql是安全的对吧?
我的建议只能是在sql进入mapper之前就做好预防

  1. 用 Preparestatement 类
  2. 自己封装一个StringUtils 类, 用来检测敏感字符

推荐2, 更加简单, 直接

新手上路,请多包涵

就算表名和字段都是不确定的,查询和更新还是要区分区分吧?

改成 select ${columns} from ${table} where ${condition} 这种,然后columns、table、condition这些进行校验,只能是一些固定内容,不知道能不能行。

另外这个功能使用的数据库用户也可以和其他功能区分开,使用mybatis-plus的dynamic-datasource可以配置多个数据源,这个服务使用一个只查询某个表的权限的用户,这样也可以稍微限制一下。

对于不确定是不可能的,你可以在information_schema查询所有表名和字段。

当然你使用mybatis肯定是有实体类的,针对实体类进行aop拦截只允许实体类的字段和表名即可;

@Aspect  
@Component  
@Slf4j  
@ConditionalOnProperty(value = "sql.statement.filter", havingValue = "true")  
public class StatementAop {

@Pointcut("@within(com.yumc.store.cpos.ikitchen.common.annotation.StatmentMethod) || @annotation(com.yumc.store.cpos.ikitchen.common.annotation.StatmentMethod) ")  
public void mapping() {  
}
.......

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.PARAMETER})
public @interface StatementColumn {
    //自定义错误
    String msg() default "错误的排序字段";
}
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.TYPE, ElementType.METHOD,ElementType.PARAMETER})
public @interface StatmentMethod {
    String[] columns() default {};
}
    @StatmentMethod
    List<ArrivalTimeConfig> selectPageInfo(ArrivalTimeConfigInput configInput);
    
    @StatmentMethod
    List<WaitingTimeConfig> selectPageInfo(@StatementColumn WaitingTimeConfigInput info);

以上代码简单演示,

使用拦截方法来验证外部传入的是否符合既定的实体所拥有的字段和对应的表名,

然后你就可以安全的使用外部的数据,

对于一层解决不了的问题 增加一层即可。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题