Pra*_*u R 111 java sql sql-injection jdbc prepared-statement
我知道PreparedStatements避免/阻止SQL注入.它是如何做到的?使用PreparedStatements构造的最终表单查询是字符串还是其他?
Pau*_*lin 185
考虑两种做同样事情的方法:
PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();
Run Code Online (Sandbox Code Playgroud)
要么
PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
Run Code Online (Sandbox Code Playgroud)
如果"user"来自用户输入并且用户输入是
Robert'); DROP TABLE students; --
Run Code Online (Sandbox Code Playgroud)
然后在第一个例子中,你会被软管.在第二个,你将是安全的,小Bobby表将在你的学校注册.
Jay*_*esh 106
要了解PreparedStatement如何阻止SQL注入,我们需要了解SQL Query执行的各个阶段.
1.编译阶段.2.执行阶段.
每当SQL Server引擎收到一个查询时,它必须通过以下阶段,
解析和规范化阶段: 在此阶段,检查Query的语法和语义.它检查查询中使用的引用表和列是否存在.它还有许多其他任务要做,但我们不详细说明.
编译阶段: 在此阶段,查询中使用的关键字如select,from,where等将转换为可由机器理解的格式.这是解释查询并确定要采取的相应动作的阶段.它还有许多其他任务要做,但我们不详细说明.
查询优化计划: 在此阶段,创建决策树以查找可以执行查询的方式.它找出了执行查询的方式的数量以及与执行Query的每种方式相关的成本.它选择执行查询的最佳计划.
缓存: 在查询优化计划中选择的最佳计划存储在缓存中,以便每当下次同一查询进入时,它不必再次通过阶段1,阶段2和阶段3.当下次查询进入时,它将直接在Cache中检查并从那里拾取执行.
执行阶段:
在此阶段,执行提供的查询并将数据作为ResultSet对象返回给用户.
PreparedStatements不是完整的SQL查询,并且包含占位符,这些占位符在运行时由实际的用户提供的数据替换.
每当包含占位符的任何PreparedStatment传递到SQL Server引擎时,它都会通过以下阶段
UPDATE用户设置用户名=?和密码=?WHERE id =?
以上查询将被解析,使用占位符编译作为特殊处理,优化并获得缓存.此阶段的查询已经编译并以机器可理解的格式转换.所以我们可以说存储在缓存中的Query是预编译的,只有占位符需要用用户提供的数据替换.
现在,在用户提供的数据进入运行时,从Cache中选取预编译查询,并使用用户提供的数据替换占位符.
(请记住,在使用者数据替换占位符后,不会再次编译/解释最终查询,并且SQL Server引擎将用户数据视为纯数据,而不是需要再次解析或编译的SQL;这就是PreparedStatement的优点. )
如果查询不必再次进行编译阶段,则占位符上替换的任何数据都将被视为纯数据,对SQL Server引擎没有任何意义,它直接执行查询.
注意:它是解析阶段之后的编译阶段,它理解/解释查询结构并为其提供有意义的行为.对于PreparedStatement,查询只编译一次,并且一直拾取缓存的编译查询以替换用户数据并执行.
由于PreparedStatement的一次编译功能,它没有SQL注入攻击.
您可以通过示例获取详细说明:http: //javabypatel.blogspot.in/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html
tan*_*ens 67
SQL注入的问题是,用户输入用作SQL语句的一部分.通过使用预准备语句,您可以强制将用户输入作为参数的内容进行处理(而不是作为SQL命令的一部分).
但是,如果您不将用户输入用作预准备语句的参数,而是通过将字符串连接在一起来构建SQL命令,那么即使使用预准备语句,您仍然容易受到SQL注入的攻击.
Tra*_*man 26
PreparedStatement中使用的SQL是在驱动程序上预编译的.从那时起,参数作为文字值而不是SQL的可执行部分发送给驱动程序; 因此,不能使用参数注入SQL.PreparedStatements的另一个有益的副作用(预编译+仅发送参数)是在多次运行语句时提高性能,即使参数的值不同(假设驱动程序支持PreparedStatements),因为驱动程序不必执行SQL解析和编译参数改变的时间.
| 归档时间: |
|
| 查看次数: |
95452 次 |
| 最近记录: |