应用程序不会直接对数据库进行操作,而是通过数据库生产商提供的数据库驱动程序来间接地对数据库进行操作。
SUN公司为了简化开发人员对数据库的统一操作,提供了一个Java操作数据库的规范,俗称JDBC。这些规范的实现由具体的数据库生产商去做,开发人员只需要掌握JDBC接口的操作即可。
package jdbcProject;
//第一步:导入必须的包
import java.sql.*;
public class jdbcDemo01 {
//第二步:说明JDBC驱动的名称和数据库的地址
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/school?" +
"useUnicode=true&characterEncoding=utf-8&useSSL=true";//连接school数据库
//Oracle--(jdbc:oracle:thin:@localhost:1521:sid)
//第三步:说明数据库的认证账户及密码
static final String USER = "root";
static final String PASS = "123456";
public static void main(String[] args) throws ClassNotFoundException, SQLException{
//第四步:注册JDBC驱动
Class.forName(JDBC_DRIVER);
//第五步:获得数据库连接
Connection connection = DriverManager.getConnection(DB_URL,USER,PASS);
//第六步:执行查询语句
Statement statement = connection.createStatement();
String sql = "SELECT * FROM student";
ResultSet rs =statement.executeQuery(sql);
while (rs.next())
{
String studentno = rs.getString("studentno");
String loginpwd=rs.getString("loginpwd");
String studentname=rs.getString("studentname");
String sex=rs.getString("sex");
String gradeid=rs.getString("gradeid");
String phone=rs.getString("phone");
String address=rs.getString("address");
String borndate=rs.getString("borndate");
String email=rs.getString("email");
String identitycard = rs.getString("identitycard");
System.out.println(studentno+"\t"+loginpwd+"\t"+studentname+"\t"+sex+"\t"
+gradeid+"\t"+phone+"\t"+address+"\t"+borndate+"\t"+email+"\t"+identitycard);
}
//第七步:关闭连接资源
rs.close();
statement.close();
connection.close();
}
}
//在不知道列的数据类型情况下使用
ResultSet.getObeject();
//获取指定的数据类型
ResultSet.getInt();
ResultSet.getFloat();
ResultSet.getDate();
ResultSet.beforeFirst();//移动到最前面
ResultSet.afterLast();//移动到最后面
ResultSet.next();//移动到后一行
ResultSet.previous();//移动到前一行
ResultSet.absolute(row);//移动到指定的row行
ResultSet.close();
Statement.close();
Connection.close();//Connection非常消耗资源,
Db.properties配置文件如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/school?useUnicode=true&&characterEncoding=utf-8&useSSL=true
username=root
password=123456
提取工具类JdbcUtils代码如下:
package jdbcProject.lesson02.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
//提取工具类
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
static {
try {
InputStream in=JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
driver=properties.getProperty("driver");
url=properties.getProperty("url");
username=properties.getProperty("username");
password=properties.getProperty("password");
//1.驱动只要加载一次
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
//2.获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//3.释放连接资源
public static void releaseResourse(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
if(resultSet!=null){
resultSet.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
}
}
TestSelect.java文件代码如下:
package jdbcProject.lesson02;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
public static void main(String[] args) throws SQLException {
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//执行查询操作
connection= JdbcUtils.getConnection();//获取数据库连接
statement=connection.createStatement();//获取SQL的执行对象
String sql="select * from grade";
resultSet=statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("gradeid")+"|"+resultSet.getString("gradename"));
}
System.out.println("查询成功!");
} catch (
SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.releaseResourse(connection,statement,resultSet);
}
}
}
TestDelete.java文件代码如下:
package jdbcProject.lesson02;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDelete {
public static void main(String[] args) throws SQLException {
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//执行删除操作
connection= JdbcUtils.getConnection();//获取数据库连接
statement=connection.createStatement();//获取SQL的执行对象
String sql="delete from grade where gradeid=6";
int i=statement.executeUpdate(sql);
if(i>0){
System.out.println("删除成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.releaseResourse(connection,statement,resultSet);
}
}
}
package jdbcProject.lesson02;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.*;
public class TestInsert {
public static void main(String[] args) throws SQLException {
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//执行插入操作
connection= JdbcUtils.getConnection();//获取数据库连接
statement=connection.createStatement();//获取SQL的执行对象
String sql="insert into grade(gradeid, gradename)\n" +
"values(6,'研一')";
int i=statement.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.releaseResourse(connection,statement,resultSet);
}
}
}
package jdbcProject.lesson02;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) throws SQLException {
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//执行更新操作
connection= JdbcUtils.getConnection();//获取数据库连接
statement=connection.createStatement();//获取SQL的执行对象
String sql="update grade set gradename='研二' where gradeid=6";
int i=statement.executeUpdate(sql);
if(i>0){
System.out.println("更新成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.releaseResourse(connection,statement,resultSet);
}
}
}
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
寻找到SQL注入的位置
判断服务器类型和后台数据库类型
针对不同的服务器和数据库特点进行SQL注入攻击
为什么Statement会被sql注入
因为Statement之所以会被sql注入是因为SQL语句结构发生了变化。比如:
"select * from tablename where username='"+uesrname+
"'and password='"+password+"'"
在用户输入’or true or’之后sql语句结构改变。
select * from tablename where username=''or true or'' and password=''
这样本来是判断用户名和密码都匹配时才会计数,但是经过改变后变成了或的逻辑关系,不管用户名和密码是否匹配该式的返回值永远为true。
为什么Preparement可以防止SQL注入
因为Preparement样式为
select * from tablename where username=? and password=?
该SQL语句会在得到用户的输入之前先用数据库进行预编译,这样的话不管用户输入什么用户名和密码的判断始终都是并的逻辑关系,防止了SQL注入。
总结:参数化能防注入的原因在于,语句是语句,参数是参数,参数的值并不是语句的一部分,数据库只按语句的语义跑,至于跑的时候是带一个普通背包还是一个怪物,不会影响行进路线,无非跑的快点与慢点的区别。
SQLInjection.java代码如下:
package jdbcProject.lesson02;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLInjection {
public static void main(String[] args) throws SQLException {
//login("张伟","123456");//正常登录方式
login("'or' 1=1","'or' 1=1");//SQL会被拼接 or
}
//登录业务
public static void login(String username, String password) throws SQLException {
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//执行查询操作
connection= JdbcUtils.getConnection();//获取数据库连接
statement=connection.createStatement();//获取SQL的执行对象
String sql="select * from student where studentname='"+username+"' and loginpwd='"+password+"'";
resultSet=statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("studentname")+"\t "+resultSet.getString("loginpwd"));
}
System.out.println("查询成功!");
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.releaseResourse(connection,statement,resultSet);
}
}
}
运行结果如下,读取了表中所有的用户名和密码:
TestInsert.java代码如下:
package jdbcProject.lesson03;
import jdbcProject.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestInsert {
public static void main(String[] args) throws SQLException {
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try{
connection=JdbcUtils.getConnection();
//区别
//使用?占位符代替参数
String sql="insert into grade(gradeid, gradename) values(?,?)";
preparedStatement=connection.prepareStatement(sql);//预编译SQL,不立马执行
preparedStatement.setInt(1,7);//gradeid
preparedStatement.setString(2,"研三");
int i=preparedStatement.executeUpdate();
if(i>0){
System.out.println("插入成功!");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JdbcUtils.releaseResourse(connection,preparedStatement,resultSet);
}
}
}
运行结果如下: