嘉兴市城市建设门户网站,广东深圳是一个城市吗,俄文网站建设 俄文网站设计,专业生产车间设计图纸网站链接#xff1a;https://juejin.im/post/5e131203e51d4541082c7db3Mybatis这个框架在日常开发中用的很多#xff0c;比如面试中经常有一个问题#xff1a;$和#的区别#xff0c;它们的区别是使用#可以防止SQL注入#xff0c;今天就来看一下它是如何实现SQL注入的。什么是S… 链接https://juejin.im/post/5e131203e51d4541082c7db3Mybatis这个框架在日常开发中用的很多比如面试中经常有一个问题$和#的区别它们的区别是使用#可以防止SQL注入今天就来看一下它是如何实现SQL注入的。什么是SQL注入在讨论怎么实现之前首先了解一下什么是SQL注入我们有一个简单的查询操作根据id查询一个用户信息。它的sql语句应该是这样select * from user where id 。我们根据传入条件填入id进行查询。如果正常操作传入一个正常的id比如说2那么这条语句变成select * from user where id 2。这条语句是可以正常运行并且符合我们预期的。但是如果传入的参数变成 or 11这时这条语句变成select * from user where id or 11。让我们想一下这条语句的执行结果会是怎么它会将我们用户表中所有的数据查询出来显然这是一个大的错误。这就是SQL注入。Mybatis如何防止SQL注入在开头讲过可以使用#来防止SQL注入它的写法如下select idsafeSelect resultMaptestUser SELECT * FROM user where id #{id}select在mybatis中查询还有一个写法是使用$它的写法如下select idunsafeSelect resultMaptestUser select * from user where id ${id}select当我们在外部对这两个方法继续调用时发现如果传入安全的参数时两者结果并无不同如果传入不安全的参数时第一种使用#的方法查询不到结果(select * from user where id or 11)但这个参数在第二种也就是$下会得到全部的结果。并且如果我们将sql进行打印会发现添加#时向数据库执行的sql为:select * from user where id or 11 它会在我们的参数外再加一层引号在使用$时它的执行sql是select * from user where id or 11。弃用$可以吗我们使用#也能完成$的作用并且使用$还有危险那么我们以后不使用$不就行了吗。并不是它只是在我们这种场景下会有问题但是在有一些动态查询的场景中还是有不可代替的作用的比如动态修改表名select * from ${table} where id #{id}。我们就可以在返回信息一致的情况下进行动态的更改查询的表这也是mybatis动态强大的地方。如何实现SQL注入的不用Mybatis怎么实现其实Mybatis也是通过jdbc来进行数据库连接的如果我们看一下jdbc的使用就可以得到这个原因。#使用了PreparedStatement来进行预处理然后通过set的方式对占位符进行设置而$则是通过Statement直接进行查询当有参数时直接拼接进行查询。所以说我们可以使用jdbc来实现SQL注入。看一下这两个的代码:public static void statement(Connection connection) { System.out.println(statement-----); String selectSql select * from user; // 相当于mybatis中使用$拿到参数后直接拼接 String unsafeSql select * from user where id or 11;; Statement statement null; try { statement connection.createStatement(); } catch (SQLException e) { e.printStackTrace(); } try { ResultSet resultSet statement.executeQuery(selectSql); print(resultSet); } catch (SQLException e) { e.printStackTrace(); } System.out.println(---****---); try { ResultSet resultSet statement.executeQuery(unsafeSql); print(resultSet); } catch (SQLException e) { e.printStackTrace(); }}public static void preparedStatement(Connection connection) { System.out.println(preparedStatement-----); String selectSql select * from user;; //相当于mybatis中的#先对要执行的sql进行预处理设置占位符然后设置参数 String safeSql select * from user where id ?;; PreparedStatement preparedStatement null; try { preparedStatement connection.prepareStatement(selectSql); ResultSet resultSet preparedStatement.executeQuery(); print(resultSet); } catch (SQLException e) { e.printStackTrace(); } System.out.println(---****---); try { preparedStatement connection.prepareStatement(safeSql); preparedStatement.setString(1, or 1 1 ); ResultSet resultSet preparedStatement.executeQuery(); print(resultSet); } catch (SQLException e) { e.printStackTrace(); }}public static void print(ResultSet resultSet) throws SQLException { while (resultSet.next()) { System.out.print(resultSet.getString(1) , ); System.out.print(resultSet.getString(name) , ); System.out.println(resultSet.getString(3)); }}总结Mybatis中使用#可以防止SQL注入$并不能防止SQL注入Mybatis实现SQL注入的原理是调用了jdbc中的PreparedStatement来进行预处理。确认过眼神