jdbc动态条件查询防止sql注入的解决方案

问题场景:这里的动态查询是指,select语句的某一个或多个查询条件是这种情况:不限或指定值。不限就是这个条件要去掉,指定值就是这个条件必须要。

比如你会看到买房子的网站的查询选项是这样的:

  • 地区:不限或北京、上海、…。(下拉选项)
  • 类型:不限或二手房或新房。(下拉选项)
  • 户型:不限或三室一厅、三室二厅、二室一厅、…。(下拉选项)

也可能还有更多的条件。

分析:如果地区条件用户选不限,sql查询的where语句中地区条件就不能要,如果选北京或某个城市,地区条件要就加上。其它条件也是这样。这种情况下,sql语句不是固定的,怎么办?

解决方案:

一.动态拼接sql语句。(不推荐)

这种方法不安全,因为会有sql注入的风险。在java的jdbc中动态拼接sql语句因为其中?号这种替代符的位置和数目不是固定的,因此不能使用preparedStatement来防止sql注入。

二.写存储过程。(推荐)

存储过程不仅可以解决动态sql语句的问题,还能有效解决sql注入的问题。

比如上面提到的这个例子,写一个查询的存储过程

DELIMITER &&
create PROCEDURE get_houses_by_conditions(IN p_city varchar(30),IN p_type INTIN p_layout INT)
begin
select * from `tb_house` house where (house.`city` = p_city or p_city is null) and (house.`type` =p_type or p_type is null ) and (house.`layout` =p_layout or p_layout is null );
end
&&

城市这个参数实际可能是INT类型的,这里只是举个例子。实际情况下,还要加上limit来做分页,这个也不要纠结。

调用的时候,参数可以传NULL或某个指定值,比如:

查询所有不限条件的房子:
call get_houses_by_conditions(NULL,NULL,NULL);

查询北京的所有房子:
call get_houses_by_conditions(‘北京’,NULL,NULL);

使用JDBC操作数据库时,因为要使用PreparedStatement来防止sql注入,那么sql语句就可以这么写了
String sql=”call get_houses_by_conditions(?,?,?);”
然后根据用户的选择,我们将问号通配符替换成NULL或具体值。

附上删除存储过程的代码
DELIMITER &&
DROP PROCEDURE get_houses_by_conditions;
&&

你可能感兴趣的:(java)