`
ccx20060810501
  • 浏览: 32679 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

PrepareStatement的优势

阅读更多

PrepareStatement相对Statement的优势:
·消除SQL注入的安全漏洞
·Statement会是数据库频繁编译SQL,可能造成数据库缓冲区的溢出
·数据库和相关驱动都可以对PrepareStatement进行优化

 

JdbcUtils工具类:

/**
 * 有关mysql数据库的工具类,单例模式SingleTon
 */
package mysql.base;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 
 * 2009-9-24 湖南大学 计算机与通信学院 计算机科学与技术专业
 * 
 * @author 陈春晓
 * 
 */
public final class JdbcUtils {
	private static String url = "jdbc:mysql://localhost:3306/test";
	private static String username = "root";
	private static String password = "xiaochun";

	private static JdbcUtils instance = null;

	private JdbcUtils() {
	};

	public static JdbcUtils getInstance() {
		if (instance == null) {
			synchronized (JdbcUtils.class) {
				if (instance == null)
					instance = new JdbcUtils();
			}
		}
		return instance;
	}

	// 保证驱动只装载一次
	static {
		// 注册驱动,只需要一次
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 获取一个数据库连接
	 * 
	 * @return Connection
	 * @exception SQLException
	 */
	public Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, username, password);
	}

	/**
	 * 释放资源
	 * 
	 * @param ResultSet
	 *            rs
	 * @param Statement
	 *            st
	 * @param Connection
	 *            conn
	 */
	public void free(ResultSet rs, Statement st, Connection conn) {
		try {
			if (rs != null)
				rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (st != null)
					st.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				try {
					if (conn != null)
						conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
 


测试代码:

/**
 * 测试SQL注入问题,要处理这个漏洞,就需要用PreparedStatement类代替Statement
 */
package mysql.base;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 
 * 2009-9-24 湖南大学 计算机与通信学院 计算机科学与技术专业
 * 
 * @author 陈春晓
 * 
 */
public class SQLInject {

	/**
	 * @param args
	 * @throws SQLException
	 */
	public static void main(String[] args) throws SQLException {
		// TODO Auto-generated method stub
		read("xiali"); // 测试SQL inject安全漏洞
		read1("xiali");
	}

	/**
	 * 读取数据库,使用PrepareStatement类可以消除sql注入漏洞
	 * 
	 * @param name
	 * @throws SQLException
	 */
	public static void read(String name) throws SQLException {
		// 有SQL inject安全漏洞
		String sqlStr = "select id,name,birthday,money from user where name=?";
		// System.out.println(sqlStr);
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			// 注册驱动,只需要一次
			// Class.forName("com.mysql.jdbc.Driver");
			// 建立连接
			conn = JdbcUtils.getInstance().getConnection();
			
			//long start =System.currentTimeMillis();
			// 创建语句
			ps = conn.prepareStatement(sqlStr);
			// 添加参数
			ps.setString(1, name);
			// 执行语句
			rs = ps.executeQuery();
			// 处理结果
			while (rs.next()) {
				System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t"
						+ rs.getObject("birthday") + "\t" + rs.getObject("money"));
			}
			//long end=System.currentTimeMillis();
			//System.out.println("Statement:read() "+(end-start)+"ms");
		} finally {
			JdbcUtils.getInstance().free(rs, ps, conn);
		}
	}

	/**
	 * 存在SQL 注入安全漏洞
	 * 
	 * @param name
	 * @throws SQLException
	 */
	public static void read1(String name) throws SQLException {
		// 有SQL inject安全漏洞
		String sqlStr = "select id,name,birthday,money from user where name='" + name + "'";
		// System.out.println(sqlStr);
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try {
			// 注册驱动,只需要一次
			// Class.forName("com.mysql.jdbc.Driver");
			// 建立连接
			conn = JdbcUtils.getInstance().getConnection();
			//long start =System.currentTimeMillis();
			// 创建语句
			st = conn.createStatement();
			// 执行语句
			rs = st.executeQuery(sqlStr);
			// 处理结果
			while (rs.next()) {
				System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t"
						+ rs.getObject("birthday") + "\t" + rs.getObject("money"));
			}
			//long end=System.currentTimeMillis();
			//System.out.println("Statement:read() "+(end-start)+"ms");
		} finally {
			JdbcUtils.getInstance().free(rs, st, conn);
		}
	}
}
分享到:
评论
1 楼 Hetal 2011-12-22  
求解:preparestatement是如何防注入的?底层如何实现的?谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics