为什么占位符可以防止sql注入?

先看下面用占位符来查询的一句话

String sql = "select * from administrator where adminname=?";
psm = con.prepareStatement(sql);

String s_name ="zhangsan‘ or ‘1‘=‘1";
psm.setString(1, s_name);

假设数据库表中并没有zhangsan这个用户名,

用plsql运行sql语句,可以查出来所有的用户名,但是在Java中并没有查出任何数据,这是为什么呢?

首先,setString()的源码中只有方法名字,并没有任何过程性处理,

那么答案肯定出现在Java到数据库这个过程中,也就是mysql和oracle驱动包中,在mysql驱动包中,PreparedStatement继承并实现了jdk中的setString方法,

也就是原因在于数据库厂商帮你解决了这个问题,下面就看看这个方法的具体实现:

public void setString(int parameterIndex, String x) throws SQLException {
        // if the passed string is null, then set this column to null
        if (x == null) {
            setNull(parameterIndex, Types.CHAR);
        } else {
            StringBuffer buf = new StringBuffer((int) (x.length() * 1.1));
            buf.append(‘\‘‘);

            int stringLength = x.length();

            //
            // Note: buf.append(char) is _faster_ than
            // appending in blocks, because the block
            // append requires a System.arraycopy()....
            // go figure...
            //
            for (int i = 0; i < stringLength; ++i) {
                char c = x.charAt(i);

                switch (c) {
                case 0: /* Must be escaped for ‘mysql‘ */
                    buf.append(‘\\‘);
                    buf.append(‘0‘);

                    break;

                case ‘\n‘: /* Must be escaped for logs */
                    buf.append(‘\\‘);
                    buf.append(‘n‘);

                    break;

                case ‘\r‘:
                    buf.append(‘\\‘);
                    buf.append(‘r‘);

                    break;

                case ‘\\‘:
                    buf.append(‘\\‘);
                    buf.append(‘\\‘);

                    break;

                case ‘\‘‘:
                    buf.append(‘\\‘);
                    buf.append(‘\‘‘);

                    break;

                case ‘"‘: /* Better safe than sorry */
                    if (this.usingAnsiMode) {
                        buf.append(‘\\‘);
                    }

                    buf.append(‘"‘);

                    break;

                case ‘\032‘: /* This gives problems on Win32 */
                    buf.append(‘\\‘);
                    buf.append(‘Z‘);

                    break;

                default:
                    buf.append(c);
                }
            }

            buf.append(‘\‘‘);

            String parameterAsString = buf.toString();

            byte[] parameterAsBytes = null;

            if (!this.isLoadDataQuery) {
                parameterAsBytes = StringUtils.getBytes(parameterAsString,
                        this.charConverter, this.charEncoding, this.connection
                                .getServerCharacterEncoding(), this.connection
                                .parserKnowsUnicode());
            } else {
                // Send with platform character encoding
                parameterAsBytes = parameterAsString.getBytes();
            }

            setInternal(parameterIndex, parameterAsBytes);
        }
    }

所以转义后的sql为‘zhangsan\‘ or \‘1\‘=\‘1‘;这个时候是查不出来的。

时间: 2024-10-12 20:56:35

为什么占位符可以防止sql注入?的相关文章

ADO.NET 占位符(防SQL 注入攻击)

当在添加程序中注入攻击时在控制台应用程序中可以这样写: 请输入编号:U006 请输入用户名:无敌 请输入密码:1234 请输入昵称:呵呵 请输入性别:True 请输入生日:2000-1-1 请输入民族:N004');update Users set PassWord='0000';-- 添加成功! 这样,不仅添加成功一条数据,而且数据库中Users表里的所有数据的密码都被修改成了0000.数据被篡改了,数据库被成功注入攻击. 那么我们怎么来防御这种注入攻击呢? 其实很简单,只需要修改下程序,在添

占位符,SQL注入?

这两天在上课时被同学拿了一段代码问我,这段代码有什么问题,我看了一会说:Connection和PreparedStatement都没关.他说不止这方面的问题,还有sql注入的问题,我就坚决的说使用了占位符不存在sql注入的问题,但是他提出了一种情况,在我看来也很有道理的情况. pstmt = conn.prepareStatement("delete from user where user.id=?"); pstmt.setString(1, "w"); 他认为如

通过jdbc使用PreparedStatement,提升性能,防止sql注入

为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行一次都要对传入的SQL语句编译一次,效率较差.     某些情况下,SQL语句只是其中的参数有所不同,其余子句完全相同,适用于PreparedStatement.PreparedStatement的另外一个好处就是预防sql注入攻击     PreparedStatement是接口,继承自State

Mybatis之占位符与拼接符

1.占位符 1.1  含义: 在持久化框架中,为了将约束条件中的可变参数从sql中分离出来,在原有的参数位置使用特殊的标记来标记该位置,后期通过代码给sql传递参数(即实现sql与代码分离开).这个特殊的标记被称为占位符. 1.2 优点: 1.2.1 防止sql注入,提高了安全性 1.2.2 对于只有参数不同的sql语句,只需要编译一次{以后会从缓存中获取} 1.3 形式: 占位符在持久化框架中的一般形式为:?.Mybatis为了更加方便的与参数列表进行映射,采用的形式为:#{参数名} 1.4

SQL或HQL预编译语句,能够防止SQL注入,但是不能处理%和_特殊字符

最近项目在做整改,将所有DAO层的直接拼接SQL字符串的代码,转换成使用预编译语句的方式.个人通过写dao层的单元测试,有以下几点收获. dao层代码如下 //使用了预编译sql public List<IndvConfigModel> selectConfigBySuffix(String suffix) { String hql = "from IndvConfigModel where configKey like '%'||?||'%'"; return this.

SQl语句中使用占位符的优点

1.增加SQL代码可读性2.占位符可以预先编译,提高执行效率3.防止SQL注入4用占位符的目的是绑定变量,这样可以减少数据SQL的硬解析,所以执行效率会提高不少 绑定变量是Oracle解决硬解析的首要利器,能解决OLTP系统中library cache的过度耗用以提高性能 绑定变量是Oracle解决硬解析的首要利器,能解决OLTP系统中library cache的过度耗用以提高性能.然刀子磨的太快,使起来锋利,却容易折断.凡事皆有利弊二性,因地制宜,因时制宜,全在如何权衡而已.本文讲述了绑定变量

Mybatis 中 sql 语句的占位符 #{} 和 ${}

#{} 表示一个占位符号,通过 #{} 可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换.#{} 可以有效防止   sql注入.#{} 可以接收简单类型值或 pojo 属性值. 如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称. ${} 表示拼接sql串,通过 ${} 可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,不能防止 sql 注入问

深入Spring Boot:那些注入不了的Spring占位符(${}表达式)

Spring里的占位符 spring里的占位符通常表现的形式是: <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="${jdbc.url}"/> </bean> 或者 @Confi

C#sql语句如何使用占位符

背景:在程序中,写sql语句时,可能要根据变量的值不同,SQL语句产生相应的变化.比如说存在变量StuName,根据变量值的不同,检索不同姓名的学生记录,这时需用到占位符的知识. 1,{0}占位符,代码如下: 1 string sql=@"select top 1 * from Student where StuName='{0}'"; 2 sql = string.Format(sql, "李四"); 以上代码即是在Student数据表中,查询学生姓名为“李四”的