mybatis的#{}和${}的区别以及order by注入问题

#{}至关于jdbc中的preparedstatementmysql

${}是输出变量的值sql

你可能说不明因此,没关系咱们看2段代码:安全

String sql = "select * from admin_domain_location order by ?";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "domain_id");
System.out.println(st.toString());

  ResultSet rs = st.executeQuery();
  while(rs.next()){
  System.out.println(rs.getString("domain_id"));
  }
输出结果:

com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location order by 'domain_id'
4
2

这是个jdbc的preparedstatement例子,不要吐槽我这么写是否合法,这里只是为了说明问题.dom

以上例子有得出如下信息:code

1)order by后面若是采用预编译的形式动态输入参数,那么实际插入的参数是一个字符串,例子中是:order by 'domain_id'排序

2)输出结果并无排序,从sql语句中的形式咱们也能够推测出此sql语句根本也不合法(正常应该是 order by domain_id)字符串

修改以上代码以下:get

String input = "domain_id";
String sql = "select * from admin_domain_location order by "+input;
PreparedStatement st = con.prepareStatement(sql);
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
    System.out.println(rs.getString("domain_id"));
}
输出结果:

com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location order by domain_id
3
5

这次咱们直接把一个变量的值拼接sql语句,从结果能够看出来:input

1)sql语句拼接正常io

2)查询结果排序正常

你可能要问这和#{}与${}有什么关系..

上面已经说过#{}至关于jdbc的preparedstatement,因此以上的第一个例子就至关于#{},那么第二个例子就天然而然指的是${}的状况.

你可能说思惟仍是有些凌乱,没关系咱们来看第三个例子:

String sql = "select * from admin_domain_location where domain_id=?";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "2");
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
    System.out.println(rs.getString("domain_id"));
}
=======================================
String input = "2";
String sql = "select * from admin_domain_location where domain_id='"+input+"'";
PreparedStatement st = con.prepareStatement(sql);
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
    System.out.println(rs.getString("domain_id"));
}

输出结果都为:
com.mysql.jdbc.PreparedStatement@12bf560: select * from admin_domain_location where domain_id='2'

这第三个例子说的是#{}和${}通用的问题,也就是说在此种状况下#{}和${}是通用的,只不过须要些小的转换.如例子中须要手动

拼接单引号 ' ' 到变量值的先后,确保sql语句正常.

简单说#{}是通过预编译的,是安全的,而${}是未通过预编译的,仅仅是取变量的值,是非安全的,存在sql注入.

这里先说一下只能${}的状况,从咱们前面的例子中也能看出,order by是确定只能用${}了,用#{}会多个' '致使sql语句失效.此外还有一个like 语句后也须要用${},简单想一下

就能明白.因为${}仅仅是简单的取值,因此之前sql注入的方法适用此处,若是咱们order by语句后用了${},那么不作任何处理的时候是存在sql注入危险的.你说怎么防止,那我只

能悲惨的告诉你,你得手动处理过滤一下输入的内容,如判断一下输入的参数的长度是否正常(注入语句通常很长),更精确的过滤则能够查询一下输入的参数是否在预期的参数集合中..

** P.S.:感谢蓝萝卜blu!您的文章解决了个人问题!**

相关文章
相关标签/搜索