sql注入问题
写在前面! 别把数据库名 数据库密码 和 sql语句的用户名 和 sql语句的 用户密码混淆!!!
Tips:原判断sql语句:String sql = "select id,name,password,email,birthday from t_user where name='" + username + "' and password='" + password + "'";
在之前写的登录功能中,随便输入一个用户名,在密码部分输入下面内容:
123' or 1='1
这个密码肯定是不正确的,但是依然能够登录成功,这个就是sql注入问题,也就是说之前写的登录功能有安全问题。为什么会导致这样的问题?我们将最终执行的sql打印可以看到是这样的:
select id,name,password,email,birthday from t_user where name='tb' and password='123' or 1='1';
出现问题的部分是 or 1=’1’这部分,因为无论如何这部分的运算结果都是true,所以在输错用户名和密码的情况下依然登录成功了。要想解决这个问题,可以使用jdbc提供的PreparedStatement。
大概意思就是说 SQL语句的拼接出问题了 主要还是 or x = x 这段是true的 所以会登录成功! 那我们怎么去修复呢:
我们不用 Statement 了 用 PreparedStatement 这玩意
PreparedStatement
PreparedStatement是一个接口,它继承了Statement,该接口有以下几个优点:
- 性能比Statement高,会把sql预编译
- 可以解决sql注入问题
使用PreparedStatement修改登录功能的代码:
第一就是将 你要 将要防SQL注入的语句要传入的字段将他改为?(英文状态下的问号):
String sql = "select id,name,password,email,birthday from t_user where name=? and password=?"; //name=? password=?
第二就是将 Statement 改为 PreparedStatement 类,并且调用prepareStatement方法将存在占位符(?)的sql语句当做参数传过去:
PreparedStatement stmt = conn.prepareStatement(sql); //注意调用的是 connection类下的prepareStatement()方法 没有d的啊 是 prepare
第三就是调用PreparedStatement类下的 setString方法填补指定的占位符(?) 即:将?的字段填上:
setString这个方法有两个参数 :
参1: 第几个占位符(?) 下标从1开始 , 参2:填补的内容。 例:
stmt.setString(1, name); //第一个占位符啊 即name 这里将变量name作为补充 填补进去
stmt.setString(2, password); //第二个占位符啊 即password 这里将变量password 作为补充 填补进去
在sql语句中,使用?作为占位符来替代要传入的内容,通过调用PreparedStatement的setString等方法将要传入的内容作为参数传递过去。
TIPS! 当你执行查询 executeQuery() 語句時 别带参数( Sql语句)!
//!这个executeQuery语句不要带参数!记住!!因为前面已经把它用prepareStatement方法传进去了。 ResultSet QueryResult = preparedStatement.executeQuery(); //然后方可和之前的方式一样调用execute各个执行语句. // ResultSet QueryResult = preparedStatement.executeQuery(Sql_Login); //错误例子啊! 之前一直找不到哪里出问题...
...烦死.