deletefromuserwhereid=\’${value}\’
如果我通过的是:1\’或1=1——每个人都应该已经知道结果会是什么。
这里的ID是整数类型,所以无法测试。如果您有兴趣,请私下测试一下。
如果你使用上面的`#{}`,就不会有任何SQL注入问题。
![](https://img-blog.csdnimg.cn/img_convert/2ec3cde8bf0655ea5417855b0d439a37.png)
1.3 `${}` 和`#{}` 的区别
`#{}` 与JDBC 中的? 等价的占位符匹配。编译后,传递的值会添加双引号以防止SQL 注入问题。
`${}` 与传递的实际值匹配。一旦通过,SQL 语句和字符串就会组合在一起。由于${} 与其他SQL 字符串连接在一起,因此它不能防止SQL 注入问题。
显示`#{}`和`${}`生成的SQL语句。
![](https://img-blog.csdnimg.cn/img_convert/da2068fddd9856c931a520e151a25dbc.png)
Stringabc=“123”;
#{abc}=\”123\”
${值}=123;
1.4 `#{}`底层如何防止SQL注入?
1.4.1 网上的答案
网上关于此类问题的疑问很多,原因有两个。
**1)`#{}`底层使用的是预编译的PreparedStatement,所以不存在SQL注入问题。
事实上,预编译是MySQL特有的功能,与PreparedStatement无关。还有,预编译并不是我们理解的预编译,PreparedStatement底层默认是不使用预编译的(必须手动开启)。详情请参阅下文
**2) `${}` 会导致SQL 注入问题,因为`#{}` 不会产生字符串连接,但`${}` 会产生字符串连接。
这两个答案都经不起进一步的调查,最终的答案也只停留在表面,没有人知道其中的原因。
1.4.2 如何防止SQL注入?
让我们打开MySQL驱动程序源代码,看看会发生什么。
打开PreparedStatement类的setString()方法(MyBatis使用setString()方法向`#{}`传递参数,但不向`${}`传递参数)。
![](https://img-blog.csdnimg.cn/img_convert/a6c393020b2ed2e1cbc868d542eb978d.png)
setString()方法的所有源代码:
publicvoidsetString(intparameterIndex,Stringx)抛出SQLException{
同步(this.checkClosed()。getConnectionMutex()){
如果(x==null){
this.setNull(parameterIndex,1);
}除此之外{
this.checkClosed();
intstringLength=x.length();
字符串生成器缓冲区;
if(this.connection.isNoBackslashEscapesSet()){
booleanneedsHexEscape=this.isEscapeNeededForString(x,stringLength);
对象参数AsBytes;
byte[] 参数AsBytes;
if(!needsHexEscape){
参数AsBytes=null;
buf=newStringBuilder(x.length()+2);
buf.append(\’\’);
buf.append(x);
buf.append(\’\’);
if(!this.isLoadDataQuery){
参数AsBytes=StringUtils.getBytes(buf.toString(),this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),this.getExceptionInterceptor());
}除此之外{
参数AsBytes=StringUtils.getBytes(buf.toString());
}
this.setInternal(parameterIndex,parameterAsBytes);
}除此之外{
参数AsBytes=null;
if(!this.isLoadDataQuery){
parameterAsBytes=StringUtils.getBytes(x,this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),this.getExceptionInterceptor());
}除此之外{
参数AsBytes=StringUtils.getBytes(x);
}
this.setBytes(parameterIndex,parameterAsBytes);
}
返回;
}
字符串参数AsString=x;
booleanneedsQuoted=true;
if(this.isLoadDataQuery||this.isEscapeNeededForString(x,stringLength)){
需要引用=假;
buf=newStringBuilder((int)((double)x.length()*1.1D));
buf.append(\’\’);
for(inti=0;istringLength;++i){//遍历字符串得到每个字符
charc=x.charAt(i);
开关{
案例“\\u0000”:
buf.append(\’\\\’);
buf.append(\’0\’);
休息;
案例“\\n”:
buf.append(\’\\\’);
buf.append(\’n\’);
休息;
案例“\\r”:
buf.append(\’\\\’);
buf.append(\’r\’);
休息;
案例“\\u001a”:
buf.append(\’\\\’);
buf.append(\’Z\’);
休息;
案例\’\’:
if(this.usingAnsiMode){
buf.append(\’\\\’);
}
buf.append(\’\’\’\’);
休息;
案例\’\’:
buf.append(\’\\\’);
buf.append(\’\’);
休息;
案例“\\”:
buf.append(\’\\\’);
buf.append(\’\\\’);
休息;
案例“”:
外壳‘’:
if(this.charsetEncoder!=null){
CharBuffercbuf=CharBuffer.allocate(1);
ByteBufferbbuf=ByteBuffer.分配(1);
cbuf.put;
cbuf.position(0);
this.charsetEncoder.encode(cbuf,bbuf,true);
if(bbuf.get(0)==92){
buf.append(\’\\\’);
}
}
buf.append;
休息;
默认:
buf.append;
}
}
buf.append(\’\’);
参数AsString=buf.toString();
}
缓冲区=空;
byte[] 参数AsBytes;
if(!this.isLoadDataQuery){
if(需要引用){
parameterAsBytes=StringUtils.getBytesWrapped(parameterAsString,‘’’,‘’’,this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),this.getExceptionInterceptor());
}除此之外{
parameterAsBytes=StringUtils.getBytes(parameterAsString,this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),this.getExceptionInterceptor());
}
}除此之外{
参数AsBytes=StringUtils.getBytes(参数AsString);
}
this.setInternal(parameterIndex,parameterAsBytes);
this.parameterTypes[parameterIndex-1+this.getParameterIndexOffset()]=12;
}
}
}
执行`#{}`查询语句并观察断点。
![](https://img-blog.csdnimg.cn/img_convert/e8a97e476e1d5c4ba91f1984117ce301.png)
最终传递的参数为:
![](https://img-blog.csdnimg.cn/img_convert/e85268d0538b53b907cf84e642d4fc85.png)
最后传递的参数是:`\’aaa\\\’ or 1=1 –`
在数据库上运行以下SQL语句(无法查询到数据)。
select*fromuserwhereusernamelike\’aaa\’or1=1\’
![](https://img-blog.csdnimg.cn/img_convert/9692adb53a2af887dacb01a5629e6044.png)
如果我们删除添加到PreparedStatement 中的“/”会发生什么?让我们运行SQL。
select*fromuserwhereusernamelike\’aaa\’or1=1\’
![](https://img-blog.csdnimg.cn/img_convert/7355a91010d025251e46441377bad95a.png)
还可以通过MySQL日志观察`#{}`和`${}`生成的SQL语句来分析问题。
**1) 打开MySQL 日志记录:**
在MySQL配置文件的[mysqld]下添加以下配置:
#是否启用mysql日志0: off (默认值) 1: on
通用日志=1
#mysql日志存储位置
General_log_file=\”D:/query.log\”
![](https://img-blog.csdnimg.cn/img_convert/c0237eec875aa36f3e99ad73bc26c350.png)
**2)重启MySQL服务(以管理员身份运行):**
![](https://img-blog.csdnimg.cn/img_convert/654b0905130dc1ac202759c67756836d.png)
停止我的sql
网络启动mysql
使用mybatis分别运行以下两条SQL语句:
![](https://img-blog.csdnimg.cn/img_convert/4947bfabe2a90dcab037373fee5c2d85.png)
查看MySQL日志。
![](https://img-blog.csdnimg.cn/img_convert/98c22aeed45450b53fcd63a692d97676.png)
1.5 `#{}` 和`${}` 的应用场景
`#{}` 比`${}` 好得多,那么为什么`${}` 仍然存在呢?
其实“${}”也是有用途的。我们都知道“${}”连接字符串以产生一个新字符串。
1.5.1 ${} 和#{} 的用法区别
例如,需要通过模糊查询查询用户表中所有姓张的员工信息。
SQL语句是: `从名称类似\’张%\’的用户中选择*`
**此时,如果传递的参数是“Zhang”**
使用`${}` 时: `select * from user where name like \’${value}%\’`
生成的SQL 语句:`select * from user where name like \’张%\’`
哪个兄弟不知道你可以提前回答网络安全面试问题?我们整理了160多道网络安全面试题(金9银10),帮助你在网络安全面试包中脱颖而出。一周去做这件事。
工程师王兰一面试题及答案目前只对我哥有用。如果你能正确回答70% 的问题,那么你找到一份稳定的工作就不会有太大困难。
对于有1-3年工作经验后想换工作的朋友来说,这也是一个很好的资源!
【如何获取完整版在文末! ]
***93 网络安全面试问题***
![](https://img-blog.csdnimg.cn/img_convert/6679c89ccd849f9504c48bb02882ef8d.png)
![](https://img-blog.csdnimg.cn/img_convert/07ce1a919614bde78921fb2f8ddf0c2f.png)
![](https://img-blog.csdnimg.cn/img_convert/44238619c3ba2d672b5b8dc4a529b01d.png)
我就不一一截图了,因为内容太多了。
### 推荐的黑客学习资源
最后给大家分享一套完整的网络安全学习资料,对所有想学习网络安全的人都有用。
对于刚接触网络安全的学生,我们创建了详细的学习和成长路线图。这可以说是最科学、最系统的学习路线。每个人都可以遵循这个大方向。
#### 1从基础零开始
##### 学习路线
对于从未接触过网络安全的同学,我们准备了详细的**学习与成长路线图**。这可以说是最科学、最系统的学习路线。大家按照这个大方向走是没有问题的。
![图片](https://img-blog.csdnimg.cn/img_convert/acb3c4714e29498573a58a3c79c775da.gif#pic_center)
##### 路线兼容学习视频
同时,还根据成长路线提供了每个部分的支持视频。
![image-20231025112050764](https://img-blog.csdnimg.cn/874ad4fd3dbe4f6bb3bff17885655014.png#pic_center)
#关于上述#{}如何防止SQL注入?_sql相关内容来源网络仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91997.html