PrepareStatement 防止sql注入

sql注入

通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令

危害:数据库信息泄露

恶意字符:1 or 1='1'等


案例:

package com.zhiwei.database;
import java.sql.*;
public class PrepareStatementTest {

	public static void main(String[] args) {
		
		PreparedStatement ps =null;
		ResultSet rs=null;
		Connection ct=null;
		
			try {
				Class.forName("com.mysql.jdbc.Driver");
				ct = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","squirrel","xiaoyang");
				ps=ct.prepareStatement("select *from user where name='zhangsan' and '1' or 1='1'");
				rs=ps.executeQuery();
				while(rs.next()){
					int id =rs.getInt(1); 
				    String name = rs.getString(2);
				    String passwd = rs.getString(3);
				    int age=rs.getInt(4);
				    String sex=rs.getString(5);
				    System.out.println(id+"--"+name+"--"+passwd+"--"+age+"--"+sex);
				}
			
			} catch (Exception e) {
				e.printStackTrace();
			} finally{
				try {
					if(rs!=null){
						rs.close();
					}if(ps!=null){
						ps.close();
					}if(ct!=null){
						ct.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
	}
}

控制台日志:

1--zhangsan--zhangsan--10--F
2--lisi--lisi--20--M
3--wangwu--wangwu--15--M
4--maliu--maliu--13--F
5--tianqi--tianqi--18--M
6--maba--maba--19--F
22--BBBB--BBBB--16--M

数据库记录:

这里写图片描述

结果:

sql语句没有查出我们想要的数据记录,而是将所有的表的记录都查询出来了,造成数据泄露(典型的sql注入漏洞)

分析

select *from user where name='zhangsan' and '1' or 1='1'

sql语句中and的优先级高于or的优先级,因此 select *from user where name='zhangsan' and '1' or 1='1' 等价于: select *from user where (name='zhangsan' and '1') or 1='1' 因name='zhangsan' and '1' or 1='1'的最终结果都是为真,where条件就失去作用,整条sql的功能等价于:select *from user

sql优化语句

select *from user where name='zhangsan' and ('1' or 1='1')

分析

将恶意sql字符隔开,根据()的优先级大于and,因此整个sql语句的判断条件就变成name='zhangsan'和('1' or 1='1'),而('1' or 1='1')永久为真,因此整条语句就实现了对name的过滤作用,恶意sql则变得多余,但这样的sql并没有实际的使用价值


sql注入的解决方案

  • 使用PrepareStatement类的set方法,它在sql预编译的时候对sql语句进行转义,PrepareState过滤特定的字符将“干净”的二进制文件提交给数据库,因而就达不到欺骗数据库的效果 ps=ct.prepareStatement("select *from user where name=?"); ps.setString(1, "zhangsan and 1 or 1='1'"); rs=ps.executeQuery();
  • web项目中一般使用过滤器或者拦截器去过滤页面表单传过来的字符,拼接"干净"的sql语句再提交数据库执行

注意:Mybatis中 $ 只是简单的变量替换存在sql注入风向, # 会将sql语句预编译,防止sql注入

转载于:https://my.oschina.net/yangzhiwei256/blog/3013954

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值