一、SQL注入问题
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
使用Statement创建的连接,存在SQL注入问题,即获取数据的字符串可能会影响到SQL语句,从而影响整个程序。
形成原因:
读取的字符串影响SQL语句的执行,从而影响程序。
解决:
- 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了
- 即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译,不起作用
- 要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
- PreparedStatement 接口继承了java.sql.Statement
- PreparedStatement 是属于预编译的数据库操作对象
- PreparedStatement 原理:预先对SQL语句的框架进行编译,然后再给SQL语句传值
解决SQL注入的关键:
- 用户提供的信息中即使含有sql语句的关键字,但是这些关键字并没有参与编译,不起作用。
二、Statement 和 preparedStatement
- Statement 存在SQL注入问题,preparedStatement解决了SQL注入问题
- Statement 编译一次,执行一次。preparedStatement编译一次可执行n次。preparedStatement效率较高
- preparedStatement在编译阶段可以做类型的安全检查。
- 业务方面要求必须支持SQL注入的时候,Starement支持SQL注入,凡是业务方面要求进行sql拼接的,则使用Statement
- 如果只是传值,则用preparedStatement。
- PreparedStatement可以操作Blob的数据,而Statement不能
- PreparedStatement可以实现更高效的批量操作
代码:
先写Sql语句,在执行数据库对象创建,然后通过Set传值,最后执行执行语句
核心代码
String sql = "select * from user1 where name = ? and password = ? ";
//执行到此处时,会发送sql语句给DBMS,然后DBMS对sql进行预编译
ps = conn.prepareStatement(sql);
//给占位符传值
ps.setString(1,name);
ps.setString(2,pass);
rs = ps.executeQuery();
package com.java;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class PrepredStatementLogin {
public static void main(String[] args) {
//获取输入数据
Map<String,String> LoginMap = initLogin();
//处理数据 -- 通过jdbc检验数据是否满足,满足登陆成功,否则登陆失败
String name = LoginMap.get("name");
String pass = LoginMap.get("pass");
if(Login(name,pass)){
System.out.println("登录成功");
}else {
System.out.println("登陆失败");
};
}1 ·
private static boolean Login(String name,String pass) {
Boolean aa = false;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs =null;
try{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//建立连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mytest1","root","root");
//SQL语句 其中一个?是一个占位符, 占位符不能用单引号括起来
String sql = "select * from user1 where name = ? and password = ? ";
//执行到此处时,会发送sql语句给DBMS,然后DBMS对sql进行预编译
ps = conn.prepareStatement(sql);
//给占位符传值
ps.setString(1,name);
ps.setString(2,pass);
rs = ps.executeQuery();
if(rs.next()){
aa = true;
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return aa;
}
private static Map<String, String> initLogin() {
System.out.println("输入用户名");
Scanner cin = new Scanner(System.in);
String UName = cin.next();
System.out.println("请输入密码");
String UPassword = cin.next();
HashMap<String, String> map = new HashMap<>();
map.put("name",UName);
map.put("pass",UPassword);
return map;
}
}