Java:SQL注入,Properties,PreparedStatement封装

SQL注入

通过SQL代码的漏洞,进行攻击系统
例:在查询条件中输入‘’‘or 1 or’” 那么查询条件会显示的结果
[id=002, username=wangwu, salary=7898.0, age=23, depart=manage]

如何解决:数据厂商的问题
解决方案:

  1. 对Java语言中传递的字符串做预处理
  2. PrepareStatement:先由PrepareStatement 和数据库连接,对字符串进行预处理,处理结束后再去执行SQL

PrepareStatement的使用:

public static void main(String[] args){
	Connection conn = null;
	PreparedStatement ps = null;
	ResultSet rs = null;
	try{
		//此处JDBCUtil是自己封装过的
		conn = JDBCUtil.getConnection();
		//定义SQL查询语句
		String sql = "select * from tb1 where username=?";
		//Statement无法处理,使用prepareStatement
		ps = conn.prepareStatement(sql);
		//此处1代表指向前面第几个问号,后面对应其值
		ps.setString(1,"'or 1 or'");
		rs = ps.executeQuery();
		while(rs.next()){
			System.out.println(rs.getString("username")+"\t"+rs.getInt("age")+"\t"+rs.getFloat("salary"));
		}
	}catch (SQLException e){
		e.printStackTrace();
	}
}
Statement与PreparedStatement的区别
  1. Preparedstatement是预处理过的,对于批量处理可以大大提高效率
  2. 数据库只进行一次处理时,用Statement对象进行处理,Preparedstatement开销比Statement大,对于一次性操作无好处
  3. Statement每次执行SQL语句时,相关数据库都要执行SQL的编译,PrepareStatement是预编译的,支持批处理
  4. Preparedstatement对象可以防止SQL注入更加安全。

Properties

在Java.util包中,它表示的是Java语言的配置文件,是Java语言独有的配置文件。 配置文件有很多中:
XML 文件 — 配置文件 Properties 的父类是HashTable
Properties 配置文件 — 一类问价 读取文件肯定是要用流的技术,使用流读取文件时把文件的内容读取到流中。

HashTable与HashMap的区别:
1.线程安全:HashTable是线程安全的,而HashMap线程不安全
2.null值:HashMap的key可以为null,而HashTablekey不可以为空
3.继承父类:HashTable继承的是Dictionary,而HashMap继承AbstractMap,但均实现Map接口
4.初始容量:HashTable初始容量为11,HashMap为16,两者默认填充因子均为0.75
5.判断键值是否存在:HashMap用ContainsKey(),而HashTable用get()方法。

Properties里存放键值对

driverCLassname=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
user=root
password=123456
static{
	try{
	Properties p = new Properties();
	InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properities");
	p.load(in);
	driver = p.getProperty("driverCLassname");
	url = p.getProperty("url");
	user = p.getProperty("user");
	password = p.getProperty("password");
	Class.forName(driver);
	}catch (ClassNotFoundException e){
		e.printStackTrace();
	}catch (IOException e){
		e.printStackTrace();
	}
}
   static {
        try {
            Properties p = new Properties();
            InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properities");
            p.load(in);
            driver = p.getProperty("driverCLassname");
            url = p.getProperty("url");
            user = p.getProperty("user");
            password = p.getProperty("password");

            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

PreparedStatement 封装方法

更新

public void Update(String sql,String...args){
	try{
		conn = getConnection();
		ps = conn.prepareStatement(sql);
		for(int i = 0; i<args.length(); i++){
			ps.setObject(i+1,args[i]);
		}
		int bRet = ps.exectuteUpdate();
	}catch (SQLException e){
		e.printStackTrace();
	}
}

多条语句查询

	public <T> T query(Class<T> clazz,String sql,Object...args){
		
		T entity = null;
		PreparedStatement ps = null;
		try {
			conn = JDBCUtils.getConnection();
			ps = conn.prepareStatement(sql);
			
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			rs = ps.executeQuery();
			//2. 得到 ResultSetMetaData 对象
			ResultSetMetaData rsmd = rs.getMetaData();
			//3. 创建一个 Map<String, Object>   列的名称 key 列的值作为value
			Map<String, Object> values = new HashMap<>();
			
			//4. 处理结果集. 利用 ResultSetMetaData 填充 对应的 Map 对象
			if(rs.next()){
				for(int i = 0; i < rsmd.getColumnCount(); i++){
					//列的名称
					String columnLabel = rsmd.getColumnLabel(i + 1);
					//列多对应的value
					Object columnValue = rs.getObject(i + 1);
					
					values.put(columnLabel, columnValue);
				}
			}
			
			//5. 若 Map 不为空集, 利用反射创建 clazz 对应的对象
			if(values.size() > 0){
				entity = clazz.newInstance();
				//5. 遍历 Map 对象, 利用反射为 Class 对象的对应的属性赋值. 
				for(Map.Entry<String, Object> entry: values.entrySet()){
					String fieldName = entry.getKey();
					Object value = null;
					if (entry.getValue() instanceof Long) {
						value = Integer.parseInt(entry.getValue().toString());
					}else{
						value = entry.getValue();
					}
					ReflectionUtils.setFieldValue(entity, fieldName, value);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return entity;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值