【这是一个假标题】
今天看到了一个有趣的小知识,关于sql注入问题及欲执行语句的用处,在这里分享给大家。
–请看下面的一段代码,在没有发明 PrepareStatement 之前,模拟登陆注册。
public class Test{
main(...){
Scanner reader=new Scanner(System.in);
syso("请输入账号:");
String username=reader.next();
syso("请输入密码:");
String password=reader.next();
//模拟登陆
login(username,password);
}
public static void login(String username,String password){
//1:获取连接
Connection conn = MyJDBCUtils.getConnnection();
//2:执行sql
Statement stat = conn.createStatement();
String sql = "select * from user where username = ' "+username+" 'and password =' "+password+ " '";
ResultSet rs = stat.executeQuery(sql);
//3:处理结果
if(rs.next()){
System.out.println("登陆成功!");
}else{
System.out.println("登陆失败!");
}
//打印sql语句查看真正sql
//syso(sql);
//4:释放资源
MyJDBCUtils.closeAll(rs, stat, conn);
}
}
运行之后我输入正确的账号密码
//请输入账号:
csdn
//请输入密码:
123
//登陆成功!
//select * from user where username = 'csdn' and password = '123'
我输入错误的账号密码
//请输入账号:
xxx
//请输入密码
yyy'or'1=1
//登陆成功!
//select * from user where username = 'xxx' and password = 'yyy'or'1=1
相信大家看明白了 or 的作用 1=1 永远成立,所以登陆成功。
Statement接口没有能力去解决sql注入问题:
–为了解决sql注入文件Java的开发者又设计了子接口:PreparedStatemen
//使用PreparedStatement替换以上三行代码
String sql = "select * from user where username = ? and password = ?"; //占位符
PreparedStatement stat = conn.prepareStatement(sql); //该方法对sql做一个预处理
//确定占位符的值
stat.setObject(1, username); //确定第一个占位符的值
stat.setObject(2, password); //确定第二个占位符的值
//执行sql
ResultSet rs = stat.executeQuery(); //指定的sql的时候,stat应该指定sql的所有内容
//打印sql语句
System.out.println(stat);
接下来我输入正确的账号密码:
//请输入账号:
csdn
//请输入密码:
123
//登陆成功!
//select * from user where username = 'csdn' and password = '123'
输入错误的密码:
//请输入账号:
csdn
//请输入密码:
yyy'or'1=1
//登陆失败!
//select * from user where username = 'xxx' and password = 'yyy\'or\'1=1
相信你们又看懂了,原来预处理语句对用户输入的敏感字眼做了处理输入的符号被转义成为yyy’or’1=1 整体的字符串 而不再将or 作为 sql语句的语法。
注: 打印 PrepareStatement 可以把sql语句打印出来。