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

深入理解 SQL 注入漏洞及解决方案

一、引言

在当今数字化时代,数据库作为存储和管理数据的核心组件,其安全性至关重要。SQL 注入是一种常见且极具威胁性的数据库安全漏洞,它可能导致数据泄露、篡改甚至系统被完全控制。本文将深入探讨 SQL 注入漏洞的产生原因、表现形式以及如何有效地解决这一问题。

二、SQL 注入漏洞的产生效果

在已知用户名的情况下,攻击者可以通过输入特殊构造的密码,利用 SQL 注入漏洞绕过系统的身份验证机制,成功登录系统。例如,原本需要正确的用户名和密码才能访问的系统,攻击者只需输入特定的字符组合,如 “aaa'or'1=1” 作为密码(用户名已知),就可以在不知道正确密码的情况下登录进去,这显然严重破坏了系统的安全性和访问控制机制。

三、SQL 注入漏洞的产生原因

SQL 注入漏洞的产生主要源于应用程序在拼接 SQL 语句时没有对用户输入进行充分的验证和过滤。以常见的登录场景为例,后台程序拼接 SQL 语句的代码通常如下:

String sql = "select * from t_user where username = '"+username+"' and password = '"+password+"'";

在这种情况下,如果用户输入恶意的字符,就会改变 SQL 语句的逻辑。比如,当用户输入 “aaa'or'1=1” 作为密码时,拼接后的 SQL 语句变为:

String sql = "select * from t_user where username = 'aaa'or'1=1' and password = 'sfsdfsds";

由于 “or '1=1'” 恒为真,无论密码是否正确,该查询都能返回结果,从而导致攻击者绕过了密码验证。

按照 AND 优先级高于 OR 的规则,它会先计算 '1=1' and password = '123456' 这部分,然后再与前面的 username = 'aaa' 通过 OR 进行运算。

如果 '1=1' 恒为 true,当 password = '123456' 结果为 false 时,'1=1' and password = '123456' 结果为 false ,但由于前面有 OR 连接 username = 'aaa' ,只要 username = 'aaa' 为 true ,整个表达式的结果就为 true ,这就可能导致不符合预期的查询结果,也是 SQL 注入利用的一个原理基础。

另一种常见的恶意输入是 “aaa'‐‐ '”,拼接后的 SQL 语句变为:

String sql = "select * from t_user where username = 'aaa'‐‐ '' and password = 'sfsdfsdfs";

“‐‐” 在 SQL 中是注释符,这使得后面的密码验证部分被注释掉,查询只验证用户名,同样也实现了非法登录。

四、SQL 注入漏洞的解决方案

为了解决 SQL 注入漏洞,我们可以使用PreparedStatement接口,它是Statement的子接口,具有以下优势:

  1. 预编译功能PreparedStatement能够将 SQL 语句中的参数部分使用 “?”(占位符)来代替,并先将编写的 SQL 语句发送到 MySQL 服务器端进行编译。编译后的 SQL 语句格式固定,后续传入的任何值都会作为 “?” 的参数处理,从而避免了恶意输入改变 SQL 语句逻辑的情况。
  2. 具体使用方法
    • 获取预编译对象:通过Connection接口的prepareStatement(String sql)方法来预编译 SQL 语句。例如:
Connection conn = JdbcUtils.getConnection();
String sql = "select * from y_user where username =? and password =?";
PreparedStatement stmt = conn.prepareStatement(sql);
  • 设置参数值:使用setXxxx()系列方法(如setString()setInt()等)向 “?” 传入值,参数的位置从 1 开始计数。例如:
stmt.setString(1,username);
stmt.setString(2,password);
  • 执行 SQL 语句:根据 SQL 语句的类型,使用executeQuery()方法执行查询操作(返回结果集),使用executeUpdate()方法执行增删改操作。例如:
ResultSet rs = stmt.executeQuery();

五、示例代码分析

以下是一个完整的 Java 代码示例,展示了如何模拟 SQL 注入漏洞以及如何使用PreparedStatement解决该问题:

package cn.qcby.demo1;import cn.qcby.utils.JdbcUtils;import java.sql.*;/*** 演示SQL注入的问题,漏洞* 在已知用户名的情况下,通过sql语言关键字,登录系统。密码随意输入的。* SQL注入产生原因是SQL语句的拼接,利用SQL关键字产生效果。* 需要解决SQL注入的问题** 解决SQL注入问题,采用SQL语句预编译的方式,把SQL语句中的参数使用?占位符来表示,先把SQL语句编译,格式固定的。* 再给?传入值,传入任何内容都表示值。数据库会判断SQL执行的结果。*/
public class JdbcTest4 {public static void main(String[] args) {// 模拟登录的功能,有SQL注入的问题//String result = new JdbcTest4().login("aaa'or'1=1", "1234sdf");//System.out.println(result);String result = new JdbcTest4().login2("aaa'or'1=1", "123456");System.out.println(result);}/*** 采用预编译的方式,解决SQL注入的问题* @param username* @param password* @return*/public String login2(String username,String password){Connection conn = null;// 预编译执行SQL语句对象PreparedStatement stmt = null;ResultSet rs = null;try {// 获取到连接conn = JdbcUtils.getConnection();// 使用?占位符String sql = "select * from y_user where username =? and password =?";// 预编译SQL语句,把SQL语句固定//Statement statement = conn.createStatement();//statement不能防止sql注入问题    prepareStatement 能够防止sql注入问题stmt = conn.prepareStatement(sql);// 需要给?设置值stmt.setString(1,username);stmt.setString(2,password);// 执行SQL语句rs = stmt.executeQuery();// 遍历数据if(rs.next()){// 表示存在数据,如果存在,说明用户名和密码编写正确return "登录成功...";}else{return "登录失败了...";}} catch (SQLException e) {e.printStackTrace();}finally {JdbcUtils.close(conn,stmt,rs);}return null;}/*** 模拟登录的功能,通过用户名和密码从数据库中查询* @param username* @param password* @return*/public String login(String username,String password){Connection conn = null;Statement stmt = null;ResultSet rs = null;try {// 获取到连接conn = JdbcUtils.getConnection();// 编写SQL语句的拼接  '1=1' true  password = '1234sdfsce' false  true and false  整体上false// String sql = "select * from t_user where username = 'aaa' or '1=1' and password = '1234sdfsce'";// String sql = "select * from t_user where username = 'aaa' or false";String sql = "select * from y_user where username = '"+username+"' and password = '"+password+"'";// 执行sqlstmt = conn.createStatement();// 执行rs = stmt.executeQuery(sql);// 遍历数据if(rs.next()){// 表示存在数据,如果存在,说明用户名和密码编写正确return "登录成功...";}else{return "登录失败了...";}} catch (SQLException e) {e.printStackTrace();}finally {JdbcUtils.close(conn,stmt,rs);}return null;}}

相关文章:

深入理解 SQL 注入漏洞及解决方案

一、引言 在当今数字化时代,数据库作为存储和管理数据的核心组件,其安全性至关重要。SQL 注入是一种常见且极具威胁性的数据库安全漏洞,它可能导致数据泄露、篡改甚至系统被完全控制。本文将深入探讨 SQL 注入漏洞的产生原因、表现形式以及如…...

Next.js 学习-1

Next.js学习 引用:https://www.nextjs.cn/learn/basics/create-nextjs-app 先试试水吧,正好dify用的这个构建的前端项目。 使用 如果您尚未安装 Node.js,请 从此处安装。要求 Node.js 10.13 或更高版本。 好吧得用新的了,记得…...

[ComfyUI]Recraft贴图开源方案,实现服装印花自由

一、介绍 今天发现了一个简单又好用的插件,可以实现类似Recraft的贴图功能,这是一个作者开发的ComfyUI插件,叫做Comfyui-Transform 这个插件比我们简单的图像覆盖多了一些可控参数,形状、透明度、倾斜、拉升和混合模式等诸多可控…...

JavaScript 数组连接方法

在 JavaScript 中,有多种方法可以连接数组。每种方法都有其自身的优点和缺点。常见的方法包括 concat()、扩展运算符(...)、push()、splice()、slice()、join()、forEach()、reduce() 以及 Array.from() 等。下面是这些方法的详细说明和示例代码。 1. concat() co…...

Windows安装MySQL教程

1.下载 下载地址:https://www.mysql.com/downloads/ 下载版本:MySQL Installer for Window 2.安装MySQL 以下只列出需要注意的一些界面,没出现的界面默认继续即可。 1.选择安装类型 提供了多种安装模式,包括默认开发版、仅…...

VOS3000线路对接、路由配置与路由分析操作教程

一、VOS3000简介 VOS3000是一款常用的VoIP运营平台,支持多种线路对接和路由配置,适合新手快速上手。本教程将带你了解如何对接线路、配置路由以及进行路由分析。 二、线路对接 准备工作 获取线路信息:从供应商处获取线路的IP地址、端口、用…...

PiscTrace的开发者版

基于 PiscTrace 架构的视图处理的纯开发板,支持静态图片、实时视频流、摄像头视频流和网络视频流的处理。与 PiscTrace 应用版相比,开发者版通过直接的代码开发,提供了更高的灵活性和可定制性,适用于需要深度定制和复杂处理的应用…...

OnlyOffice:前端编辑器与后端API实现高效办公

OnlyOffice:前端编辑器与后端API实现高效办公 一、OnlyOffice概述二、前端编辑器:高效、灵活且易用1. 完善的编辑功能2. 实时协作支持3. 自动保存与版本管理4. 高度自定义的界面 三、后端API:管理文档、用户与权限1. 轻松集成与定制2. 实时协…...

github 怎么创建一个私有repository 并从另外一台电脑拉取下来更新

1.github上新建一个repository 设置为private tips删除在这 点setting 然后往下拖动 会有个这里是用来删项目的 2.另外 一台电脑拉取这个repository的时候 需要配置 一个ssh key 这个key的内容生成参考本地电脑的生成 然后在这配置 2.1 生成 SSH 密钥(如果还没有…...

本周行情——250222

本周A股行情展望与策略 结合近期盘面特征及市场主线演化,本周A股预计延续结构性分化行情,科技成长与政策催化板块仍是资金主战场,但需警惕高标股分歧带来的波动。以下是具体分析与策略建议: 1. 行情核心驱动因素 主线延续性&…...

分发糖果(力扣135)

题目说相邻的两个孩子中评分更高的孩子获得的糖果更多,表示我们既要考虑到跟左边的孩子比较,也要考虑右边的孩子,但是我们如果两边一起考虑一定会顾此失彼。这里就引入一个思想:先满足右边大于左边时的糖果分发情况,再…...

QML ToolButton与DelayButton的使用、详解与自定义样式

QML MenuBarItem与MenuItem的使用、详解与自定义样式 一、介绍1、ToolButton常见用法基础示例设置图标 常用属性texticonenabledshortcutcheckable & checked 信号onClickedonPressed 和 onReleased 样式和外观使用场景 2、DelayButton使用场景核心属性1. delay 核心信号1.…...

动态规划

简介 动态规划最核心两步: 状态表示:dp[i]代表什么状态转移方程:如何利用已有的dp求解dp[i] 只要这两步搞对了, 就完成了动态规划的%95 剩下的就是细节问题: dp初始化顺序(有时是倒序)处理边…...

SQL FIRST() 函数详解

SQL FIRST() 函数详解 在SQL中,FIRST() 函数是一个用于处理查询结果的聚合函数。它通常与 GROUP BY 子句结合使用,用于返回每个分组中的第一个记录。本文将详细解释 FIRST() 函数的用法、参数、返回值以及与它的关联函数。 1. 函数概述 FIRST() 函数的…...

ClickHouse系列之ClickHouse安装

ClickHouse系列之ClickHouse安装 1 ClickHouse2 Docker安装ClickHouse2.1 docker 启动脚本2.2 默认用户及密码2.3 8123和9000端口的作用2.3.1 81232.3.2 9000 3 Clickhouse连接3.1 命令行客户端连接3.1.1 常见的客户端脚本3.1.1.1 查看数据库:show databases;3.1.1.…...

大模型监督微调(SFT)技术解析

大模型监督微调(SFT)技术深度解析 一、基本知识介绍 监督微调(Supervised Fine-Tuning)是连接预训练与具体应用的关键技术层。其本质是通过特定任务的标注数据,在保持预训练模型核心能力的前提下,调整模型…...

PTA: 有序顺序表的合并

请设计一个能够将有序顺序表LA,LB进行合并的算法,要求合并后的顺序表LC依然有序。 例如: LA的元素 1 3 5 7 LB的元素 2 4 LC的元素 1 2 3 4 5 7 其中,LA和LB的长度不超过1000,当中的元素为非递减排序。 输入格式: 第…...

Vuetify解决与旧版浏览器(如Internet Explorer 11)的兼容性问题‌

简介 由于Vuetify使用了ES2015/2017的特性,这些特性在旧版浏览器中可能不被支持,因此需要通过配置来确保这些特性能够被正确转换。 配置1 在项目项目根目录下的vue.config.js文件,或nuxt.config.ts中,添加 transpileDependencies …...

android,flutter 混合开发,pigeon通信,传参

文章目录 app效果native和flutter通信的基础知识1. 编解码器 一致性和完整性,安全性,性能优化2. android代码3. dart代码 1. 创建flutter_module2.修改 Android 项目的 settings.gradle,添加 Flutter module3. 在 Android app 的 build.gradl…...

Shell文档归档、压缩与解压

Shell文档归档、压缩与解压 1、文件归档与压缩2、zip、gzip与tar指令2.1、zip指令2.2、gzip指令2.3、tar指令 1、文件归档与压缩 归档文件是指将一组文件或目录保存到一个文件中;压缩文件是指将一组文件或目录按照某种存储格式保存到一个文件中,所占磁盘…...

【Bluedroid】AVRCP 连接源码分析(一)

一、AVRCP协议简介 AVRCP(Audio/Video Remote Control Profile)是蓝牙协议栈中的一个重要部分,它定义了蓝牙设备之间的音视频传输控制的流程和特点。AVRCP使得用户可以通过一个蓝牙设备(如手机)远程控制另一个蓝牙设备(如蓝牙耳机或音箱)上的音视频播放,如播放、暂停、…...

CMake入门

1.什么是CMake Makefile想必大家都不陌生吧,它能够解决我们的自动化编译问题,大多是IDE软件都集成了make,譬如 Visual C的 nmake、linux 下的 GNU make、Qt 的 qmake 等等。 不同的IDE所集成的make工具所遵循的规范和标准都不同,也…...

基于vite6创建项目

pnpm create vue vite已自动配置路径,在.config.js jsconfig.json 中 按需引用element-plus 官网中有 pnpm install element-plus npm install -D unplugin-vue-components unplugin-auto-import // vite.config.ts import { defineConfig } from vite import Aut…...

简单封装一个websocket构造函数

问题描述 最近维护一个老项目,发现项目中有大量重复代码,特别是websocket的调用这一块,同样的代码复制了十几个页面,于是自己封装了一个websocket调用的构造函数。 export default class CreateWebSocket {constructor(url) {//…...

大模型产品Deepseek(八)、数据嵌入+知识库管理+联网搜索,实现精准的知识查询

如何将数据嵌入到DeepSeek中以实现精准的知识查询 1. 目标 DeepSeek是一个强大的基于大模型的知识查询工具,能够通过数据嵌入和智能查询功能提供精确的答案。本文将详细介绍如何在DeepSeek中进行数据嵌入,以便最大化其在实际应用中的价值。 2. 推荐使用的Page Assist插件 …...

探索Vue:数字翻滚动画的实现与优化

在前端开发中,动画效果总能为用户界面增添一抹生动与趣味。今天,我们将深入剖析一个基于Vue 3实现的数字翻滚动画组件,从代码结构到功能实现,再到性能优化,一步步揭开它的神秘面纱。 组件概述 这个Vue组件名为Number…...

POI pptx转图片

前言 ppt页面预览一直是个问题&#xff0c;office本身虽然有预览功能但是收费&#xff0c;一些开源的项目的预览又不太好用&#xff0c;例如开源的&#xff1a;kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老&#xff0c;使用版本较旧 <dependency><gro…...

力扣LeetCode: 2506 统计相似字符串对的数目

题目&#xff1a; 给你一个下标从 0 开始的字符串数组 words 。 如果两个字符串由相同的字符组成&#xff0c;则认为这两个字符串 相似 。 例如&#xff0c;"abca" 和 "cba" 相似&#xff0c;因为它们都由字符 a、b、c 组成。然而&#xff0c;"aba…...

DeepSeek模型量化

技术背景 大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;&#xff0c;可以通过量化&#xff08;Quantization&#xff09;操作来节约内存/显存的使用&#xff0c;并且降低了通讯开销&#xff0c;进而达到加速模型推理的效果。常见的就是把Float16的浮…...

如何调整CAN位宽容忍度?

CAN位宽容忍度是指在控制器局域网络&#xff08;CAN, Controller Area Network&#xff09;中允许时钟同步的误差范围。这是CAN网络正常通信时的关键因素之一&#xff0c;因为CAN协议依赖位同步来确保多个节点在总线上正确解码数据。CAN位宽容忍度确保节点之间由于时钟偏差或抖…...

Versal - 基础6(Linux 开发 AIE-ML + 自动化脚本解析)

目录 1. 简介 2. 步骤解析 2.1 概览 2.1.1 步骤依赖关系 2.1.2 总目录结构 2.2 Vitis XPFM 2.2.1 Dir 2.2.2 Makefile 2.2.3 vitis_pfm.py 2.3 Kernels 2.3.1 Dir 2.3.2 Makefile 2.3.3 config 文件 2.4 AIE_app 2.4.1 Dir 2.4.2 Makefile 2.4.3 aie 要点 2.…...

乐享数科:供应链金融—三个不同阶段的融资模式

供应链金融是与产业链紧密结合的融资模式&#xff0c;它主要体现在订单采购、存货保管、销售回款这三个不同的业务阶段&#xff0c;并针对这些阶段提供了相应的金融服务。以下是这三个阶段中主要的融资模式及其特点&#xff1a; 供应链金融融资模式主要分为以下几种&#xff1…...

vmware虚拟机Ubuntu Desktop系统怎么和我的电脑相互复制文件、内容

1、先安装vmware workstation 17 player&#xff0c;然后再安装Ubuntu Desktop虚拟机&#xff0c;然后再安装vmware tools&#xff0c;具体可以参考如下视频&#xff1a; VMware虚拟机与主机实现文件共享&#xff0c;其实一点也不难_哔哩哔哩_bilibili 2、本人亲自试过了&…...

【React】React 基础(2)

JSX 是什么 JSX是一种 JavaScript 的语法扩展(extension), 也在很多地方称之为 JavaScript XML, 因为看起就是一段XML语法。它用于描述我们的Ul界面&#xff0c;并且其完成可以和 JavaScript 融合在一起使用&#xff1b; 为什么 React 选择使用 jsx&#xff1f; React 认为渲…...

DeepSeek接入Siri(已升级支持苹果手表)完整版硅基流动DeepSeek-R1部署

DeepSeek接入Siri&#xff08;已升级支持苹果手表&#xff09;完整版硅基流动DeepSeek-R1部署 **DeepSeek** 是一款专注于深度学习和人工智能的工具或平台&#xff0c;通常与人工智能、机器学习、自动化分析等领域有关。它的主要功能可能包括&#xff1a;深度学习模型搜索&…...

ASP.NET MVC AJAX 文件上传

如何使用 MVC 5 和 AJAX&#xff08;.NET Framework&#xff09;上传文件。 使用AJAX和ASP.NET MVC 上传文件 再简单不过了。对于最纯粹的人来说&#xff0c;这不需要使用jQuery。此代码实际上允许上传多个文件。 注意&#xff1a;以下代码示例支持 ASP.NET MVC 5。如果使用 .…...

npm使用了代理,但是代理软件已经关闭导致创建失败

如果在关闭前打开了vscode&#xff0c;此时vscode中的终端没有刷新&#xff0c;就会出现这个问题&#xff0c;最开始会一直转圈圈&#xff0c;直到超时&#xff0c;然后出现该报错 ❯ npm create vuelatest npm error code ECONNREFUSED npm error syscall connect npm error …...

Spring Boot定时任务原理

Spring Boot定时任务原理 在现代应用中&#xff0c;定时任务的调度是实现周期性操作的关键机制。Spring Boot 提供了强大的定时任务支持&#xff0c;通过注解驱动的方式&#xff0c;开发者可以轻松地为方法添加定时任务功能。本文将深入探讨 Spring Boot 中定时任务的实现原理…...

公文派2025:免费社区版重大安装更新!

大家好&#xff0c;感谢对「公文派」的支持。 距离上一次更新已经过去了将近一年的时间&#xff0c;今天我们带来了全新的免费2025社区版&#xff0c;该版本也是目前最新的版本&#xff0c;无需授权即可使用所有的功能。 我们先来看下本版本的更新及特色功能 聚合多个AI功能…...

Ubuntu24.04LTS的下载安装超细图文教程(VMware虚拟机及正常安装)

&#x1f638;个人主页&#x1f449;&#xff1a;神兽汤姆猫 &#x1f4d6;系列专栏&#xff1a;开发语言环境配置 、 Java学习 、Java面试 、Markdown等 学习上的每一次进步&#xff0c;均来自于平时的努力与坚持。 &#x1f495;如果此篇文章对您有帮助的话&#xff0c;请点…...

ES6相关操作

一.JavaScript的基础语法 1.Demo1.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JavaScrip…...

【运维】源码编译安装cmake

背景&#xff1a; 已经在本地源码编译安装gcc/g&#xff0c;现在源码安装cmake 下载源码 下载地址&#xff1a;CMake - Upgrade Your Software Build System 安装步骤&#xff1a; ./bootstrap --prefix/usr/local/cmake make make install 错误处理 1、提示找不到libmpc.…...

代码随想录_回溯

代码随想录_回溯 回溯 77.组合 77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 思路: 回溯 优化: 剪枝 注意代码中i&#xff0c;就是for循环里选择的起始位置。 for (int i startIndex; i <…...

tauri2实现监听记住窗口大小变化,重启回复之前的窗口大小

要想实现记住窗口大小的功能&#xff0c;整体逻辑就是要监听窗口大小变化&#xff0c;将窗口大小保存下来&#xff0c;重启之后&#xff0c;读取保存的大小&#xff0c;然后恢复。这里可以使用rust层实现&#xff0c;也可以在前端实现。我这里就纯rust层实现了。 监听窗口变化…...

番茄工作法html实现

对比了deepseek-r1-online和本地部署的14b的版本&#xff0c;输出的输出的html页面。 在线满血版的功能比较强大&#xff0c;可以一次完成所有要求。14b版本的功能有一些欠缺&#xff0c;但是基本功能也是写了出来了。 input write a html named Pomodoro-clock which “hel…...

C++:dfs,bfs各两则

1.木棒 167. 木棒 - AcWing题库 乔治拿来一组等长的木棒&#xff0c;将它们随机地砍断&#xff0c;使得每一节木棍的长度都不超过 5050 个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态&#xff0c;但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序…...

【ORB-SLAM3】鲁棒核函数的阈值设置

问题背景 阈值 δ \delta δ 是 Huber 鲁棒核函数的重要参数。首先给出结论&#xff0c;在ORB-SLAM系列中&#xff0c;该阈值选取的原则为&#xff1a; 单目情况下&#xff0c;根据95%置信水平下两自由度卡方检验的临界值&#xff0c; δ \delta δ 设置为 5.991 \sqrt{5.9…...

四种常见图形库GLUT,SDL,SFML和GLFW简介

GLUT、SDL、SFML 和 GLFW 是四种常用的库&#xff0c;用于管理窗口、输入和上下文创建&#xff0c;通常与 OpenGL 结合使用以实现图形渲染。以下是它们的详细介绍、常用应用场合和具体案例。 1. GLUT&#xff08;OpenGL Utility Toolkit&#xff09; 简介 GLUT 是一个用于创建…...

C++类和对象进阶:初始化列表和static成员深度详解

C类和对象&#xff1a;初始化列表和static成员深度详解 1. 前言2. 构造函数初始化成员变量的方式2.1 构造函数体内赋值2.2 初始化列表2.2.1 初始化列表的注意事项 2.3 初始化列表的初始化顺序 3. 类的静态成员3.1 引入3.2 静态成员变量3.3 静态成员函数3.4 静态成员的注意事项3…...

[C#]C# winform部署yolov12目标检测的onnx模型

yolov12官方框架&#xff1a;github.com/sunsmarterjie/yolov12 【测试环境】 vs2019 netframework4.7.2 opencvsharp4.8.0 onnxruntime1.16.3 【效果展示】 【调用代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.…...