既然这么险恶的环境等着我,那我只好变|

理暗

园龄:2年9个月粉丝:1关注:0

JDBC连接数据库出现的SQL注入问题

JDBC连接数据库出现的SQL 注入的问题

SQL存在漏洞,会被攻击导致数据泄露。

SQL注入是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

 

1、新建 db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123

2、提取工具类

JdbcUtils.java

复制代码
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();
        }
    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //释放连接资源
    public static void release(Connection conn, Statement st, ResultSet rs){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}
复制代码

3.SQL注入问题代码

使用statement对象向数据库发送SQL语句

复制代码
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SQL_Pour_Into {
    public static void main(String[] args) {

        //login("laoliu","123456");
        login("'or '1=1","'or '1=1");//此时也能登陆成功,不管username和password是否正确,1=1为真,语句就为真,就能登录成功!

    }

    //登录业务
    public static void login(String username,String password){

        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();

            String sql = "select * from users where `name`='"+username+"' AND `password` ='"+password+"'";

            rs = st.executeQuery(sql);
            while (rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("password"));
                System.out.println("登录成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }

    }
}
复制代码

使用PreparedStatement对象后代码如下:

复制代码
import com.zhuang.lesson02.utils.JdbcUtils;

import java.sql.*;

public class SQl_Pour_Into {
    public static void main(String[] args) {

        login("laoliu","123");
        //login("'or '1=1","'or '1=1");//此时就不能登录成功了

    }

    //登录业务
    public static void login(String username,String password){

        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();

            //PreparedStatement防止SQL注入的本质,把传递进来的参数当做字符
            String sql = "select * from users where name=? and password=?";

            st = conn.prepareStatement(sql);

            st.setString(1,username);
            st.setString(2,password);

            rs = st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("password"));
                System.out.println("登录成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }

    }
}
复制代码

由上面代码可以得知,JDBC连接数据库时,使用PreparedStatement对象可以防止SQL注入,效率更好!

 

4、解决SQL注入

  1. 严格的参数校验

    参数校验就没得说了,在一些不该有特殊字符的参数中提前进行特殊字符校验即可。

  2. SQL预编译

    SQL预编译具体是怎样防止SQL注入的呢?实际上当将绑定的参数传到MySQL服务器,MySQL服务器对参数进行编译,即填充到相应的占位符的过程中,做了转义操作。我们常用的JDBC就有预编译功能,不仅提升性能,而且防止SQL注入。

本文作者:理暗

本文链接:https://www.cnblogs.com/Li-An/p/16475699.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   理暗  阅读(100)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起