JDBC的复习(三):Sql注入问题和解决
Sql注入问题
用户名:
dasa
密码:
dasa' or '1' = '1
登陆成功!
根本原因:
用户输入的信息中含有sql语句的关键字,并且这些关键字参与了sql语句的编译过程,导致原来的sql语句意思被扭曲,进而达到sql注入。
解决Sql注入
- 只要用户提供的信息不参与SQl的编译过程,就可以解决该问题
- 即使用户输入的语句中含有SQL语句的关键字,到那时没有参与编译,不起作用。
- 使用PrePareStatement进行sql语句框架的预编译。
/**
* 登陆函数,判断登陆是否成功
* @param userLoginInfo
* @return 返回登陆是否成功
*/
private static boolean Login(Map<String, String> userLoginInfo) {
boolean flag = false;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String userName = userLoginInfo.get("useName");
String passWord = userLoginInfo.get("passWord");
try {
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?characterEncoding=UTF8&useSSL=false","root","001204");
//3. 获取操作对象
//SQL语句的框架
String sql = "select * from userinfo where userName = ? and passWord = ?";
ps = conn.prepareStatement(sql);
//占位符,第一?下标是1,第二个?下表是标记
ps.setString(1,userName);
ps.setString(2,passWord);
//4. 执行sql语句
rs = ps.executeQuery();
//5. 处理查询结果集合
if(rs.next()){
flag = true;
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
//释放资源
if(rs!=null){
rs.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
//释放资源
if(ps!=null){
ps.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
//释放资源
if(conn!=null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
return flag;
}
Statement和PrePareStatement的对比
- Statement存在sql注入问题,PrePareStatement解决了这个问题
- Statement是编译一次执行一次,PrePareStatement是编译一次执行N次,相比较而言,效率更高
- PrePareStatement会在编译阶段做类型的安全性检查
Statement的作用演示
package com.bjpowernode.jdb;
import java.sql.*;
import java.util.Scanner;
import static java.lang.System.exit;
/**
* @author 31200
*/
public class JdbcTest08 {
public static void main(String[] args) {
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
while(true){
System.out.println("请输入desc表示降序或者asc表示升序:");
Scanner scanner = new Scanner(System.in);
//获取到输入的信息
String character = scanner.nextLine();
if(!("desc".equals(character) || "asc".equals(character))){
System.out.println("输入有误区,请重新输入!!!");
continue;
}
try {
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?characterEncoding=UTF8&useSSL=false","root","001204");
//3. 获取数据库操作对象
stat = conn.createStatement();
//4. 执行sql语句
String sql = "select ename from emp order by ename " + character;
rs = stat.executeQuery(sql);
//5. 遍历结果集
System.out.println("-------------------------------");
while(rs.next()){
String ename = rs.getString("ename");
System.out.println(ename);
}
exit(0);
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放资源
try {
if(rs!=null){
rs.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(stat!=null){
stat.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(conn!=null){
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}