当前位置: 首页 > news >正文

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);}}
}
​

相关文章:

  • 46-4 等级保护 - 网络安全等级保护概述
  • 构建 deno/fresh 的 docker 镜像
  • 解锁 LLMs 的“思考”能力:Chain-of-Thought(CoT) 技术推动复杂推理的新发展
  • 数智教育创新如何向未来?腾讯云与你探索革新之路
  • 捋清UITableView展示不同类型数据的差异
  • 聚合分析是Elasticsearch中非常强大的工具
  • nginx 配置2级目录 刷新404
  • 建议收藏!AIGC绘画基础,Midjourney风格码style reference code策展汇总合集
  • 后端项目实战--瑞吉外卖项目软件说明书
  • 升级和维护老旧LabVIEW程序
  • 主动元数据平台详解(下):BIG 十一问,详解定位、对接、血缘保鲜等问题
  • Zookeeper高频面试题整理(入门到精通)
  • 【Mars3d】config.json中的蓝色底图map.basemap = 2017代码实现
  • Jenkins For Windows编译构建C#项目环境搭建(完整版)
  • leetcode168:Excel表列名称
  • JS 中的深拷贝与浅拷贝
  • 【mysql】环境安装、服务启动、密码设置
  • Angular 2 DI - IoC DI - 1
  • Apache的基本使用
  • Java方法详解
  • js操作时间(持续更新)
  • leetcode-27. Remove Element
  • npx命令介绍
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • ReactNativeweexDeviceOne对比
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Vue2.x学习三:事件处理生命周期钩子
  • 测试如何在敏捷团队中工作?
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 微信开源mars源码分析1—上层samples分析
  • 我的zsh配置, 2019最新方案
  • 我看到的前端
  • 想写好前端,先练好内功
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 用jquery写贪吃蛇
  • 再谈express与koa的对比
  • C# - 为值类型重定义相等性
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (4)Elastix图像配准:3D图像
  • (C++17) optional的使用
  • (java)关于Thread的挂起和恢复
  • (pojstep1.1.2)2654(直叙式模拟)
  • (pojstep1.3.1)1017(构造法模拟)
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (二)正点原子I.MX6ULL u-boot移植
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (三) diretfbrc详解
  • (算法)前K大的和
  • (算法)求1到1亿间的质数或素数