SQL中#{}和${}有何区别,#{}有何用处
Admin 2022-08-02 群英技术资讯 386 次浏览
#{}
匹配的是一个占位符,相当于 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
以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: /* 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.session.getServerSession().useAnsiQuotedIdentifiers()) { buf.append('\\'); } buf.append('"'); break; case '\032': /* This gives problems on Win32 */ 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 注入的风险。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍SQL Server聚合函数算法优化的小技巧,对大家学习SQL Server有一定的帮助,感兴趣的朋友可以参考下,希望大家阅读完这篇文章能有所收获,接下来小编带着大家一起了解看看。
SQL*Loader(SQLLDR)是Oracle的高速批量数据加载工具。这是一个非常有用的工具,可用于多种平面文件格式向Oralce数据库中加载数据,本文给大家分享sqlloader怎么使用的相关资料,感兴趣的朋友一起学习吧
数据库是用来存放数据的,我们经常会对数据进行查询操作,文本就主要介绍row_number分页查询的用法,ROW_NUMBER()函数既可以,满足分区的需求,也可以根据一定顺序排序,非常好用,感兴趣的朋友可以了解一下。
有时候需要一次性将SQLServer中的数据导出给其他部门的也许进行关联或分析,这种需求对于SSIS来说当然是非常简单,但很多时候仅仅需要一次性导出这些数据而...
MSSQL差异备份,就是和前一次备份作对比,把不一样的内容备份下来,这样,只要前一次备份后,插入新的内容,差异备份就可以把刚插入的内容备份出来,而这个备份文件将大大减少,得到webShell的成功也提高了不少! 差异备份的流程大概这样:
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008