java如何预防sql注入

1 sql注入

1.1 使用字符串拼接导致数据异常 sql语句拼接

        // 构建SQL查询语句,注意这里存在SQL注入风险
        String sql = "select name,age from user where name='" + username + "' and password ='" + password + "'";
        System.out.println("sql语句为:" + sql);

1.2 若使用超级用户名登录则造成数据泄露

    public static void main(String[] args) {
        // 测试用例1:正常用户名
        // String username = "张三";
        // 测试用例2:恶意构造的用户名,用于SQL注入攻击
        String username1 = "'or 1=1 or' '='";
        boolean flag = login(username1, "111111111111");
        System.out.println(flag);
    }

输出结果

1.3 非法登录 绕过验证

1.4 先通过用户名验证 再验证密码

          // 如果查询结果有记录,说明用户名存在
            if (resultSet.next()) {
                // 2. 继续验证取出的密码
                String pass = resultSet.getString("password");
                // 3. 继续判断数据库中的密码与用户传入的密码是否匹配
                if (pass != null && pass.equals(password)) {
                    // 密码匹配成功
                    return true;
                } else {
                    // 密码匹配失败
                    return false;
                }
            }

2 预处理

执行sql语句有 Statement PreparedStatement(防注入,特殊字符处理,效率高)

预处理使用占位符,之后再赋值

 // 使用预编译的SQL插入语句
        String sql1 = "insert into user(password,name,phone)" + "values(?,?,?)";
     // 使用预编译的SQL语句
        PreparedStatement ps = null;
        try {
            // 预编译SQL语句
            ps = conn.prepareStatement(sql1);
​
            // 为预编译语句中的占位符赋值
            ps.setString(1, "999999");
            ps.setString(2, "测试ps");
            ps.setString(3, "138457856523");
​
            // 执行预编译的SQL语句并获取影响的行数
            int row = ps.executeUpdate();
            System.out.println("-----" + row);
​

3 加载配置文件

加载配置文件

• 在文件中配置连接属性

import com.yw.utils.ConnectionUtil;
​
import java.sql.Connection;
​
public class test {
    public static void main(String[] args) {
        /**
         * 配置文件读取成功
         */
        Connection conn = ConnectionUtil.getConn();
        System.out.println(conn);
    }
}

• 在连接工具类中使用读取属性文件的方式获取连接参数

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
​
/**
 * 创建连接
 */
public class ConnectionUtil {
    /**
     * io流
     */
    private static String driver;
    private static  String url;
    private static String username;
    private static String password;
​
    static {
        InputStream is = ConnectionUtil.class.getResourceAsStream("/db.properties");
        Properties p = new Properties();
        try {
            p.load(is);
            driver = p.getProperty("driver");
            url = p.getProperty("url");
            username = p.getProperty("username");
            password = p.getProperty("password");
​
          //  password = p.getProperty("password");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
​
    /**
     * 建立连接方法
     * @return
     */
    public static Connection getConn(){
        Connection conn = null;
        try {
            Class.forName(driver);//加载驱动
            conn = DriverManager.getConnection(url,username,password);//给了三个参
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return conn;
    }
​
   public static void close(Connection connection,Statement statement,ResultSet resultSet){
      if(resultSet != null){
          try {
              resultSet.close();
          } catch (SQLException e) {
              throw new RuntimeException(e);
          }
      }
​
      if(statement != null){
          try {
              statement.close();
          } catch (SQLException e) {
              throw new RuntimeException(e);
          }
      }
​
      if(connection != null){
          try {
              connection.close();
          } catch (SQLException e) {
              throw new RuntimeException(e);
          }
      }
​
   }
}

• db.properties 直接使用文本文件进行编辑

username = root
password = root
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/java_demo1

4 元数据集

import com.sun.xml.internal.ws.addressing.WsaActionUtil;
import com.yw.utils.ConnectionUtil;
​
import java.sql.*;
​
public class test1 {
    public static void main(String[] args) {
        String sql = "select * from user";
        query(sql);
    }
​
    public static void query(String sql){
        Connection conn = ConnectionUtil.getConn();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            /*ResultSetMetaData metaData = rs.getMetaData();//元数据
            int count = metaData.getColumnCount();//获取列数
            System.out.println(count);
            for (int i = 0; i < count; i++) {
                String catalogName = metaData.getColumnName(i+1);
                int columnType = metaData.getColumnType(i + 1);
                System.out.println(catalogName+"==="+columnType);
            }*/
​
            ResultSetMetaData rsd = rs.getMetaData();//获取元数据
            String columnClassName = rsd.getColumnClassName(1);//返回字段类型
            int columnType = rsd.getColumnType(2);
            String columnName = rsd.getColumnName(1);
            String columnName1 = rsd.getColumnName(2);
            System.out.println(columnClassName+"====="+columnType+"=========="+columnName+"========"+columnName1);
​
​
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            ConnectionUtil.close(conn,ps,rs);
        }
    }
​
}

5 封装BaseDao

BaseDao

import com.yw.utils.ConnectionUtil;
​
import java.sql.*;
​
public class BaseDao {
​
    private String username ="root";
    private String password ="123456";
    private String driver ="com.mysql.cj.jdbc.Driver";
    private String url = "jdbc:mysql://localhost:3306/java_demo1";
​
    private Connection connection;//连接
    private PreparedStatement ps;//执行sql语句
    private ResultSet rs;//返回结果集
​
    /**
     * 连接方法
     * @return
     */
    public Connection getConnection(){
        try {
            if(connection == null || connection.isClosed()){ // 或者已经关闭
                Class.forName(driver);//加载驱动
                connection = DriverManager.getConnection(url,username,password);
            }
            return connection;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
​
  /*  public Connection getConnection(){
        try {
            if(connection == null || connection.isClosed()) {
                Class.forName(driver);
                connection = DriverManager.getConnection(url,username,password);
            }
            return connection;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }*/
​
  /*  public int update(String sql,Object ... params){ //sql以参数的形式传入
        connection = getConnection();
        System.out.println(sql);
        try {
            ps = connection.prepareStatement(sql);
            *//*int i = ps.executeUpdate();
            return i;*//*
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            int i = ps.executeUpdate();
            return i;
        }catch (Exception e){
            e.printStackTrace();
        }
        return -1;
    }*/
​
    /**
     * 更新方法
     * @param sql
     * @param params 增加 加一  删除 少一个  修改 where id= ? 返回影响行
     * @return
     */
    public int update(String sql,Object...params){
        connection = getConnection();//获得连接
        System.out.println(sql);
        try {
            ps = connection.prepareStatement(sql);//使用预编译 占位符
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            int i = ps.executeUpdate();//返回影响行数
            return i;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
​
​
   /* public ResultSet query(String sql,Object... params){
        System.out.println(sql);
        connection = getConnection();//连接
        try {
            ps = connection.prepareStatement(sql);//预编译
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            rs = ps.executeQuery();
            return rs;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }*/
​
    /**
     *
     * @param sql
     * @param params 查询
     * @return
     */
​
    public ResultSet Query(String sql,Object...params){
        connection = getConnection();
        try {
            ps = connection.prepareStatement(sql);
            for (int i = 1; i < params.length; i++) {
                ps.setObject(i,params[i]);
            }
            rs = ps.executeQuery();
            return rs;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
​
​
    public void close(){
        try {
           if(rs != null){
               rs.close();
               rs = null;
           }
           if(ps != null){
               ps.close();
               ps = null;
           }
           if(connection !=  null){
               connection.close();
               connection = null;
           }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
​
}

TestBase

import java.sql.ResultSet;
import java.sql.SQLException;
​
public class TestBase {
    public static void main(String[] args) throws SQLException {
       /* String sql = "insert into user(password,name,age,phone)values(?,?,?,?)";
        Object[] params = {"654321","basedao",12,"1547895132"};
        BaseDao baseDao = new BaseDao();
        int i = baseDao.update(sql,params);
        */
​
        /**
         * 测试更新方法
         */
       /* String sql = "insert into user(password,name,age,phone)values(?,?,?,?)";
        BaseDao baseDao = new BaseDao();
        Object[] params = {"898989","测试params",15,"189878564"};
        baseDao.update(sql,params);*/
/*
        String sql = "select password,name,phone from user";
        BaseDao baseDao = new BaseDao();
        ResultSet query = baseDao.query(sql);//不能关闭
        try{
            while (query.next()){
                String password = query.getString("password");
                String name = query.getString("name");
                String phone = query.getString("phone");
                System.out.println(password+name+password);
            }
        }catch (Exception e){
            e.printStackTrace();
        }*/
​
        String sql1 = "select password,name, phone from user";
        BaseDao baseDao = new BaseDao();
        ResultSet query = baseDao.Query(sql1);
        while (query.next()){
            String pass = query.getString("password");
            String name = query.getString("name");
            String phone = query.getString("phone");
            System.out.println("pass="+pass+"name="+name+"phone="+phone);
        }
    }
}
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值