iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >浅谈为什么#{}可以防止SQL注入
  • 527
分享到

浅谈为什么#{}可以防止SQL注入

2024-04-02 19:04:59 527人浏览 薄情痞子
摘要

目录#{} 和 ${} 的区别#{} 底层是如何防止 sql 注入的?为什么能防止SQL注入?#{} 和 ${} 的区别 #{} 匹配的是一个占位符,相当于 JDBC 中的一个?,会

#{} 和 ${} 的区别

#{} 匹配的是一个占位符,相当于 JDBC 中的一个?,会对一些敏感字符进行过滤,编译过后会对传递的值加上双引号,因此可以防止 SQL 注入问题。

${} 匹配的是真实传递的值,传递过后,会与 SQL 语句进行字符串拼接。${} 会与其他 SQL 进行字符串拼接,无法防止 SQL 注入问题。

<mapper namespace="com.gitee.shiayanga.mybatis.wildcard.dao.UserDao">
    <select id="findByUsername" resultType="com.gitee.shiayanga.mybatis.wildcard.entity.User" parameterType="string">
        select * from user where username like #{userName}
    </select>
    <select id="findByUsername2" resultType="com.gitee.shiayanga.mybatis.wildcard.entity.User" parameterType="string">
        select * from user where username like '%${userName}%'
    </select>
</mapper>
==>  Preparing: select * from user where username like ?
==> Parameters: '%小%' or 1=1 --(String)
<==      Total: 0
==>  Preparing: select * from user where username like '%aaa' or 1=1 -- %'
==> Parameters: 
<==      Total: 4

#{} 底层是如何防止 SQL 注入的?

  • #{} 底层采用的是 PreparedStatement,因此不会产生 SQL 注入问题
  • #{} 不会产生字符串拼接,而 ${} 会产生字符串拼接

为什么能防止SQL注入?

Mysql为例,#{} 使用的是 com.mysql.cj.ClientPreparedQueryBindings#setString 方法,在这里会对一些特殊字符进行处理:

public void setString(int parameterIndex, String x) {
        if (x == null) {
            setNull(parameterIndex);
        } else {
            int stringLength = x.length();

            if (this.session.getServerSession().isNoBackslashEscapesSet()) {
                // Scan for any nasty chars

                boolean needsHexEscape = isEscapeNeededForString(x, stringLength);

                if (!needsHexEscape) {
                    StringBuilder quotedString = new StringBuilder(x.length() + 2);
                    quotedString.append('\'');
                    quotedString.append(x);
                    quotedString.append('\'');

                    byte[] parameterAsBytes = this.isLoadDataQuery ? StringUtils.getBytes(quotedString.toString())
                            : StringUtils.getBytes(quotedString.toString(), this.charEncoding);
                    setValue(parameterIndex, parameterAsBytes, MysqlType.VARCHAR);

                } else {
                    byte[] parameterAsBytes = this.isLoadDataQuery ? StringUtils.getBytes(x) : StringUtils.getBytes(x, this.charEncoding);
                    setBytes(parameterIndex, parameterAsBytes);
                }

                return;
            }

            String parameterAsString = x;
            boolean needsQuoted = true;

            if (this.isLoadDataQuery || isEscapeNeededForString(x, stringLength)) {
                needsQuoted = false; // saves an allocation later

                StringBuilder buf = new StringBuilder((int) (x.length() * 1.1));

                buf.append('\'');

                //
                // 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: 
                            buf.append('\\');
                            buf.append('0');
                            break;
                        case '\n': 
                            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 '"': 
                            if (this.session.getServerSession().useAnsiQuotedIdentifiers()) {
                                buf.append('\\');
                            }
                            buf.append('"');
                            break;
                        case '\032': 
                            buf.append('\\');
                            buf.append('Z');
                            break;
                        case '\u00a5':
                        case '\u20a9':
                            // escape characters interpreted as backslash by mysql
                            if (this.charsetEncoder != null) {
                                CharBuffer cbuf = CharBuffer.allocate(1);
                                ByteBuffer bbuf = ByteBuffer.allocate(1);
                                cbuf.put(c);
                                cbuf.position(0);
                                this.charsetEncoder.encode(cbuf, bbuf, true);
                                if (bbuf.get(0) == '\\') {
                                    buf.append('\\');
                                }
                            }
                            buf.append(c);
                            break;

                        default:
                            buf.append(c);
                    }
                }

                buf.append('\'');

                parameterAsString = buf.toString();
            }

            byte[] parameterAsBytes = this.isLoadDataQuery ? StringUtils.getBytes(parameterAsString)
                    : (needsQuoted ? StringUtils.getBytesWrapped(parameterAsString, '\'', '\'', this.charEncoding)
                            : StringUtils.getBytes(parameterAsString, this.charEncoding));

            setValue(parameterIndex, parameterAsBytes, MysqlType.VARCHAR);
        }
    }

所以 '%小%' or 1=1 --  经过处理之后就变成了 '''%小%'' or 1=1 --'

而 ${} 只是简单的拼接字符串,不做其他处理。

这样,它们就变成了:

-- %aaa' or 1=1 --
select * from user where username like '%aaa' or 1=1 -- %'

-- '%小%' or 1=1 --
select * from user where username like '''%小%'' or 1=1 --'

所以就避免了 SQL 注入的风险。

到此这篇关于浅谈为什么#{}可以防止SQL注入的文章就介绍到这了,更多相关#{}防止SQL注入内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅谈为什么#{}可以防止SQL注入

本文链接: https://www.lsjlt.com/news/148249.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅谈为什么#{}可以防止SQL注入
    目录#{} 和 ${} 的区别#{} 底层是如何防止 SQL 注入的?为什么能防止SQL注入?#{} 和 ${} 的区别 #{} 匹配的是一个占位符,相当于 JDBC 中的一个,会对...
    99+
    2024-04-02
  • 为什么参数化查询可以防止sql注入
    参数化查询可以防止sql注入原因:参数化查询可以对参数进行过滤,还能够重用执行计划,若执行计划被重用的话,SQL所要表达的语义是不会变化的,因此参数化查询可以防止SQL注入。...
    99+
    2024-04-02
  • 哪些工具可以防止sql注入
    可以防止sql注入的工具有:SQLIer,它可以找到网站上一个有SQL注入漏洞的URL,并根据有关信息来生成利用SQL注入漏洞,但它不要求用户的交互。SQLMap是一个自动的“盲目”SQL注入工具。SQLID是一个SQL注入漏洞挖掘器,也是...
    99+
    2024-04-02
  • sql参数化为什么能防止注入
    sql参数化能防止注入是因为基于以下两点:setString(): 在WEB程序接收字符串的场景使用,它可将用户输入的参数全部强制转换为字符串,并进行适当的转义,防止了sql注入的产生。setInt(): 在WEB程序接收整型的场景使用,它...
    99+
    2024-04-02
  • 为什么预编译能防止SQL注入
    预编译能防止SQL注入是因为在运行程序第一次操作数据库之前,SQL语句已经被数据库分析、编译和优化,而且对应的执行计划也会将sql缓存下来,并允许数据库以参数化的形式进行查询,当运行时会动态地把参数传给PreprareStatement,即...
    99+
    2024-04-02
  • 浅谈SQL注入的四种防御方法
    最近了解到安全公司的面试中都问到了很多关于SQL注入的一些原理和注入类型的问题,甚至是SQL注入的防御方法。SQL注入真的算是web漏洞中的元老了,著名且危害性极大。下面这里就简单的分享一下我总结的四...
    99+
    2023-09-05
    php web安全
  • 怎么防止SQL注入
    这篇文章主要介绍了怎么防止SQL注入,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。SQL注入即是指web应用程序对用户输入数据的合法性没有判...
    99+
    2024-04-02
  • ibatis怎么防止sql注入
    ibatis防止sql注入的方法:使用#写法采用预编译方式,将转义交给数据库,则不会出现注入问题,例如://mysql环境select * from test where school_name like conca&#...
    99+
    2024-04-02
  • golang怎么防止sql注入
    在Go语言中,可以使用参数化查询或预编译语句来防止SQL注入。1. 参数化查询:使用占位符来代替实际的参数值,然后将参数值作为参数传...
    99+
    2023-09-17
    golang sql
  • mysql怎么防止sql注入
    要防止SQL注入,可以采取以下措施:1. 使用参数化查询或预编译语句:通过将用户输入的值作为参数传递给查询语句,而不是将其直接拼接到...
    99+
    2023-08-23
    mysql sql
  • hibernate怎么防止sql注入
    hibernate防止sql注入的方法:使用named parameter方法(在查询字符串中使用:),例如:usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String quer...
    99+
    2024-04-02
  • laravel怎么防止sql注入
    这篇文章主要介绍“laravel怎么防止sql注入”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“laravel怎么防止sql注入”文章能帮助大家解决问题。当你使用Eloquent查询时,如:User...
    99+
    2023-07-04
  • Mybatis防止sql注入原理是什么
    这篇文章主要讲解了“Mybatis防止sql注入原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mybatis防止sql注入原理是什么”吧!Mybatis防止sql注入原理SQL 注...
    99+
    2023-06-22
  • 为什么https可以防止dns劫持
    HTTPS是在HTTP明文通道的基础上增加了一层SSL加密通道。SSL协议是用于解决传输层安全问题的网络协议,其核心是基于公钥密码学理论实现了对服务器身份认证、数据的加密保护以及对数据完整性的校验等功能,确保传输数据的机密性和完整性,以及服...
    99+
    2024-04-02
  • cdn为什么可以防止ddos攻击
    cdn之所以能有效防止ddos攻击,主要在于它的智能化。当有ddos攻击时,它会将整个系统将被攻击的流量分散开来。一是节省了服务器的压力,二是增强了网站的工具难度。三是为服务器管理人员提供了补救的时间。所以使用这种技术可以有效的防止ddos...
    99+
    2024-04-02
  • 怎么有效防止sql注入
    这期内容当中小编将会给大家带来有关怎么有效防止sql注入,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一 背景数据如下:本系统采用mysql做为数据库,使用Jdbc来进行数据库的相关操作。系统提供了一个功...
    99+
    2023-06-15
  • Tomcat中怎么防止SQL注入
    使用预编译语句:不要直接拼接SQL语句,而是使用预编译语句,如PreparedStatement,可以将参数传递给SQL语句,而...
    99+
    2024-04-25
    Tomcat
  • 防止sql注入漏洞用什么函数
    防止sql注入漏洞可以用以下三个函数:addslashes()用于单字节字符串的处理,他是强行加/$username=addslashes($username);mysql_escape_string用于多字节字符串的处理,不考虑连接的当前...
    99+
    2024-04-02
  • 为什么要防sql语句注入
    sql注入是通过把sql命令插入到web表单提交或通过页面请求的查询字符串,最终达到欺骗服务器执行恶意的sql指令以及获得攻击者想得知的数据信息,因此我们需要通过数据库安全防护技术实现有效防护,从而避免sql注入导致数据泄露的情况。...
    99+
    2024-04-02
  • node-mysql中怎么防止SQL注入
    node-mysql中怎么防止SQL注入,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。SQL注入简介SQL注入是比较常见的网络...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作