预防sql注入最好的方法是预编译。
用java做实验。没有使用预编译的代码:
Statement statement = con.createStatement(); String sql = "select * from users where username = '" + username + "'"; logger.info(sql); ResultSet rs = statement.executeQuery(sql);
使用sql注入,注入成功:
以下是mysql日志:
使用预编译的代码:
String sql = "select * from users where username = ?"; PreparedStatement st = con.prepareStatement(sql); st.setString(1, username);
使用sql注入,注入失败:
预编译的mysql日志,可以看到使用预编译之后,对特殊字符进行了转义:
Mybatis在传参的时候,#{}会进行预编译,而${}则不会。
下面是使用${}传参:
@Select("select * from users where username = '${username}'")
List<User> findByUserNameVuln01(@Param("username") String username);
注入成功:
日志如下
接下来使用#{}传参:
@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);
注入失败:
日志如下:
问过大佬们,预编译目前很难(几乎不可能)绕过,小小的一步就能抵御大大的风险,小伙伴们用起来~>_<~