您的位置:首页 > 健康 > 养生 > 全球购物网站大全_网站制作的公司哪家效果好_seo单页面优化_百度热线电话

全球购物网站大全_网站制作的公司哪家效果好_seo单页面优化_百度热线电话

2024/12/23 8:55:01 来源:https://blog.csdn.net/m0_74124657/article/details/143648489  浏览:    关键词:全球购物网站大全_网站制作的公司哪家效果好_seo单页面优化_百度热线电话
全球购物网站大全_网站制作的公司哪家效果好_seo单页面优化_百度热线电话

目录

展示SQL攻击

举一个出现sql 攻击的例子

SQL攻击的原因

 分析原因

阻止SQL攻击

PreparedStatement的含义

使用PreparedStatement的原因

步骤如下

注意

总结


展示SQL攻击

举一个出现sql 攻击的例子

假设我们在做登录业务时,思路是这样的

  1. 首先 收集用户输入的用户名,
  2. 其次密码和数据库中用户表中的信息逐个比对,如果相同则登录成功;否则登录失败 ,表示用户表中没有该用户信息,需要注册

用户名:tom , 密码 123 。 user 表中已存在该信息

测试代码如下

   login("tom", "123");

login方法代码如下

public static void login(String username1, String password1) {String url = "jdbc:mysql://localhost:3306/dj666";String username = "root";String password = "123456";Connection conn = null;Statement statement = null;try {conn = DriverManager.getConnection(url, username, password);statement = conn.createStatement();String sql = "select * from user where pwd='" + password1 + "' and username='" + username1 + "'";ResultSet resultSet = statement.executeQuery(sql);if (resultSet.next()) {System.out.println("登录成功");} else {System.out.println("登录失败");}} catch (SQLException e) {throw new RuntimeException(e);} finally {try {if (statement != null)statement.close();else if (conn != null)conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}

因为user表 有这条用户信息,所有肯定是登录成功的

但实际上,用户在设置个人信息,不会这么简单,或许会更加的复杂

如下面所示:

login("a' or '1'='1", "a' or '1'='1");

我们知道,上面的信息在user用户表中,是没有的。也因此会登录失败

但运行后发现,“登录成功” 这就有问题!!!!!!!!!!!!

SQL攻击的原因

 分析原因

一个不存在的信息,却可以登录成功这是为什么呢

我们把用户输入的信息和查询的sql语句连起来,发现变成了一条完成的SQL查询语句

select * from user where pwd='a' or '1'='1' and username='a' or '1'='1'

发现 在我们添加 个人信息时,使用or  但在数据库中, or会被视为 关键字,并且or关键字 把用户输入的信息连接为一条完成的sql语句片段 。因此 where条件,一直是true 。即使用户表中,没有这条信息,也会被识别并登录成功。

当然,还不止于此:具体原因如下

在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!

但我们应该如何避免,既可以使用像or 这样容易被数据库看作关键字的 单词,又不会被数据库识别成关键字

阻止SQL攻击

PreparedStatement的含义

PreparedStatement叫预编译声明!

PreparedStatement是Statement的子接口,你可以使用PreparedStatement来替换Statement。

使用PreparedStatement的原因

  • 防止SQL攻击
  • 提高代码的可读性,以可维护性
  • PreparedStatement的使用

步骤如下

1 使用Connection 对象调用 PreparedStatement(String sql) 方法 参数为 我们使用的sql语句模板。变量用?表示

  String sql = "update student set stuName=?,stuAge=?,stuSex=? where stuId=?";//获取执行sql语句的对象preparedStatement = conn.prepareStatement(sql);

2 调用PreparedStatement的setXXX()系列方法为问号 “?”设置值 。占位符 从1 开始

   preparedStatement.setString(1, password1);preparedStatement.setString(2, username1);

3 调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法;

修改上面的代码如下

    //sql语句模板String sql = "select * from user where pwd=? and username=?";//获取执行sql语句的对象preparedStatement = conn.prepareStatement(sql);// 1 表示占位符的索引,从1开始preparedStatement.setString(1, password1);preparedStatement.setString(2, username1);// 调用executeQuery方法,执行sql语句ResultSet resultSet = preparedStatement.executeQuery();

注意

  • 1 SQL语句中的问号,表示参数,后面使用setxx(占位符索引,传递的实参),为参数赋值,变成一条完整的SQL语句。
  • 2 PreparedStatement 的executeQuery()方法 是没有参数的,这是PreparedStatement 独有的;而Statement的executeQuery()是需要参数(SQL语句)的

疑问,为什么PreparedStatement 的executeQuery()方法 是没有参数的?

理由如下:

因为在创建PreparedStatement对象时已经让它与一条SQL模板绑定在一起了。所以在调用它的executeQuery()和executeUpdate()方法时就不再需要参数了。

修改后login方法代码如下

  public static void login(String username1, String password1) {String url = "jdbc:mysql://localhost:3306/dj666";String username = "root";String password = "123456";Connection conn = null;PreparedStatement preparedStatement=null;try {conn = DriverManager.getConnection(url, username, password);//sql语句模板String sql = "select * from user where pwd=? and username=?";//获取执行sql语句的对象preparedStatement = conn.prepareStatement(sql);// 1 表示占位符的索引,从1开始preparedStatement.setString(1, password1);preparedStatement.setString(2, username1);// 调用executeQuery方法,执行sql语句ResultSet resultSet = preparedStatement.executeQuery();if (resultSet.next()) {System.out.println("登录成功");} else {System.out.println("登录失败");}} catch (SQLException e) {throw new RuntimeException(e);} finally {try {if (preparedStatement != null)preparedStatement.close();else if (conn != null)conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}

运行结果

发现,使用了PreparedStatement后可以处理sql攻击

总结

所以,建议大家在今后的开发中,无论什么情况,都去使用PreparedStatement,而不是使用Statement,这样可以极大的避免因输入的内容(向变量传递值)造成SQL语句和原本我们所想的SQL不同造成的结果错误。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com