JDBC 第三章 SQL注入

1.SQL注入概述

用户输入的信息中含有sql语句的关键词,并且这些关键词参与sql语句的编译过程,会导致sql语句的原意被扭曲,达到sql注入
例如输入:用户名aaa 密码aaa’ or ‘1’ = '1

String sql = "select*from t_user where loginName = '" + loginName + "' and loginPwd = '" + loginPwd + "'";

用户填入后完成sql语句的拼接,发送sql语句给DBMS,DBMS进行sql编译,将非法信息编译进入,扭曲原含义

2.解决SQL注入问题

使用java.sql.PrepareedStatement,让用户输入的信息不参与SQL语句的编译
PreparedStatement接口继承了Statement,输入预编译数据库操作对象,原理是,预先对SQL语句的框架进行编译,然后再给SQL语句传“值”。

public class JDBCTest08 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        boolean loginSuccess = false;

        Scanner s = new Scanner(System.in);
        System.out.println("用户名");
        String loginName = s.nextLine();
        System.out.println("密码");
        String loginPwd = s.nextLine();
        
        try {
            //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://loaclhoat:3306/bjpowernode", "root", "333");
            //3.获取预编译的数据库操作对象
            //一个?代表一个占位符,将来接收一个值,占位符不能用单引号括起来
            String sql = "select * from t_user where loginName = ? and loginpwd = ?";
            ps = conn.prepareStatement(sql);
            //第一个下标是1
            ps.setString(1,loginName);
            ps.setString(2,loginPwd);
            //4.执行sql
            rs = ps.executeQuery();
            //5.处理结果集
            if (rs.next()) loginSuccess = true;
            System.out.println(loginSuccess);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            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();
                }
            }
        }

    }
}

3.Statement和PreparedStatement的对比

  • Statement存在sql注入问题,PreparedStatement解决了sql注入问题
  • Statement是编译一次执行一次,PreparedStatement是编译一次执行N次,效率较高
  • PreparedStatem会在编译阶段做类型的安全检查
  • PreparedStatement使用较多,当业务方面要求必须支持SQL注入时,必须使用Statement
    示例:根据用户输入升序降序输出
public class JDBCTest09 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        Scanner scanner = new Scanner(System.in);
        System.out.println("输入desc或asc");
        String keyWords = scanner.nextLine();

        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://loaclhoat:3306/bjpowernode", "root", "333");
            stmt = conn.createStatement();
            String sql = "select ename from emp order by " + keyWords;
            rs = stmt.executeQuery(sql);
            while (rs.next()) System.out.println(rs.getString("ename"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

4.PreparedStatement完成DML

Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://loaclhoat:3306/bjpowernode", "root", "333");

String sql = "insert into dept (deptno,dname.loc) values (?,?,?)";
ps = conn.prepareStatement(sql);
ps.setInt(1,60);
ps.setString(2,"销售部");
ps.setString(3,"上海");

String sql = "update dept set dname = ?,loc = ? where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1,"研发一部");
ps.setString(2,"北京");
ps.setInt(3,60);

String sql = "delete from dept where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1,60);

int count = ps.executeUpdate();
System.out.println(count);
//5.处理结果集(不需要)
//6.释放资源

传送门

上一章:JDBC 第二章 JDBC编程六步
下一章:JDBC 第四章 JDBC事务机制

内容概要:本文档详细介绍了一款轻量级任务管理系统的构建方法,采用了Python语言及其流行Web框架Flask来搭建应用程序。从初始化开发环境入手到部署基本的CRUD操作接口,并结合前端页面实现了简易UI,使得用户能够轻松地完成日常任务跟踪的需求。具体功能涵盖新任务添加、已有记录查询、更新状态以及删除条目四个核心部分。所有交互行为都由一组API端点驱动,通过访问指定URL即可执行相应的操作逻辑。此外,在数据持久化层面选择使用SQLite作为存储引擎,并提供了完整的建模语句以确保程序顺利运行。最后,还提及未来拓展方向——加入用户权限校验机制、增强安全检查以及优化外观风格等方面的改进措施。 适合人群:熟悉Linux命令行操作并对Web编程有一定了解的技术爱好者;打算深入理解全栈开发流程或者正在寻找入门级别练手机会的朋友。 使用场景及目标:旨在为开发者传授实际动手编写小型互联网产品的技巧,尤其适用于个人作业管理或者是小团队协作场景下的待办事项追踪工具开发练习。通过亲手搭建这样一个完整但不复杂的系统,可以帮助学习者加深对于前后端协同工作流程的理解,积累宝贵的实践经验。 其他说明:虽然当前实例仅涉及较为基础的功能模块,但在掌握了这套架构的基础上,读者完全可以依据自身业务特点灵活调整功能特性,满足更多个性化定制化需求。对于初学者来说,这是一个非常好的切入点,不仅有助于掌握Flask的基础用法和技术生态,还能培养解决具体问题的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值