项目中--遇到类似问题。
一、什么是sql注入?
先举个栗子:用户登录
SELECT * From Table WHERE Name='XX' and Password='YY' and Corp='ZZ'
注入之后:SELECT * From Table WHERE Name='SQL inject' and Password='' and Corp='' or 1=1--'
可以看到注入后可以免密码登录。
相信上面的例子已经可以让你明白sql注入的危害了。下面是概念--(抄袭==)
SQL注入攻击(SQL Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞。可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作,甚至有可能获取数据库乃至系统用户最高权限。
而造成SQL注入的原因是因为程序没有有效过滤用户的输入,使攻击者成功的向服务器提交恶意的SQL查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码。
二、字符串拼接的sql?
上面的sql问题是直接使用了字符串拼接导致的,导致出现了漏洞。
三、preparestatement?
(一)优势?
preparestatement是执行sql查询的api:1、mysql会预先编译好,缓存下来以便下次重复使用;2、可以避免大部分sql注入(欢迎补充)
(二)如何避免sql注入?(贴代码了)
String sql = "SELECT * FROM EMPLOYEE WHERE ID = ?"; Connection conn = null; try { conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); Employee employee = null; ResultSet rs = ps.executeQuery(); if (rs.next()) { employee = new Employee( rs.getInt("ID"), rs.getString("NAME"), rs.getInt("AGE") ); } rs.close(); ps.close(); return employee; } catch (SQLException e) { throw new RuntimeException(e); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) {}
当然,如果使用mybatis,就可以省去这些工作了。
其他问题:
1、对order by之类的,怎么使用preparestatement呢?
解答:结合stringformat使用,先替换掉%s之类的。
参考:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
http://www.mybatis.org/mybatis-3/
http://www.mkyong.com/jdbc/jdbc-preparestatement-example-select-list-of-the-records/ (不错的例子)