<img src="https://img.php.cn/upload/article/000/000/052/5ffcf9b492b47340.jpg" alt="SQL 삽입 문제 해결" >
<img src="https://img.php.cn/upload/article/000/000/052/5ffcf9b492b47340.jpg" alt="SQL 삽입 문제 해결" >
推荐(免费):<a href="https://www.php.cn/sql/" target="_blank">SQL教程</a>
SQL
注入是什么?
看一下百度百科的定义:
啊,好长一大段文字,些许不想看,下面通过一个例子,来说明一下什么是SQL注入
:
新建一个数据库,再建一个表,添加两行数据:
use db1;create table user( id int primary key auto_increment, username varchar(32), password varchar(32));insert into user values(null,'zhangsan','123');insert into user values(null,'lisi','234');
表如下图所示:
再随随便便用JDBC
写个登陆操作:
package com.wzq.jdbc;import com.wzq.util.JDBCUtils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Scanner;/* * 需求: * 1、通过键盘录入用户名和密码 * 2、判断用户是否登陆成功 * */public class JDBCDemo05 { public static void main(String[] args) { Scanner cin = new Scanner(System.in); System.out.println("请输入用户名:"); String username = cin.nextLine(); System.out.println("请输入密码:"); String password = cin.nextLine(); boolean res = new JDBCDemo05().login(username, password); if (res) System.out.println("登陆成功!"); else System.out.println("登陆失败!"); } public boolean login(String username, String password) { if (username == null || password == null) { return false; } Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //1、获取数据库连接 conn = JDBCUtils.getConnection(); //JDBCUtils工具类 //2、定义sql String sql = "select * from user where username = '" + username + "' and password = '" + password + "'"; //3、获取执行sql的对象 stmt = conn.createStatement(); //4、执行sql rs = stmt.executeQuery(sql); return rs.next(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(rs, stmt, conn); } return false; }}
测试一下:
可以看到,普通的检验没有任何问题,现在使用SQL注入
:
账户名称随便输入,密码输入:a' or 'a'='a
惊讶的发现,居然登陆成功了。输出一下sql
看一下:
select * from user where username = 'askjdhjksahd' and password = 'a' or 'a' = 'a'
可以看到where
之后的条件,无论是什么结果都为真,都会输出整个表:
所以,综上所述:在sql
拼接时,有一些sql
的特殊关键字参与字符串的拼接,就会造成安全性问题,这就是上面为什么能登陆成功的原因所在。
那怎么解决这个问题呢?
答:利用PreparedStatement
对象,不使用Statement
对象。
PreparedStatement
对象是Statement
对象的子类,它是预编译的sql
,所以运行速度会比Statemnet
更快。
PerpaerdStatement
使用?
作为占位符,使用setXxx(索引,值)
给?
赋值
所以我们替换一下Statement
권장(무료):SQL 튜토리얼
SQL 삽입이란 무엇인가요
?
바이두 백과사전에 정의를 보세요:
SQL 삽입
이 무엇인지 예를 들어 설명하겠습니다. 🎜🎜새 데이터베이스를 만들고, 테이블을 만들고, 두 행의 데이터를 추가하세요. :🎜public boolean login(String username, String password) { if (username == null || password == null) { return false; } Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { //1、获取数据库连接 conn = JDBCUtils.getConnection(); //JDBCUtils类 //2、定义sql String sql = "select * from user where username = ? and password = ?"; //3、获取执行sql的对象 pstmt = conn.prepareStatement(sql); pstmt.setString(1,username); pstmt.setString(2,password); //4、执行sql rs = pstmt.executeQuery(); return rs.next(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(rs, pstmt, conn); } return false; }🎜표는 아래와 같습니다:🎜
JDBC
를 사용하여 로그인 작업을 작성하세요. 🎜rrreee🎜테스트해 보세요: 🎜🎜 보시다시피 일반적인 검사에는 문제가 없습니다. 이제 SQL 주입
을 사용하세요. >: 🎜🎜계정 이름은 원하는 대로 입력하세요. 비밀번호는 a' 또는 'a'='a
🎜🎜 로그인에 성공해서 놀랐습니다. sql
을 출력하고 살펴보세요: 🎜rrreee🎜 where
뒤에 조건이 표시됩니다. 어떤 결과가 true이든 전체 테이블이 출력됩니다: 🎜🎜 요약하자면: sql에서
스플라이싱 시 sql
의 일부 특수 키워드가 문자열 스플라이싱에 관여하게 되어 보안 문제가 발생하게 됩니다. 이것이 위의 로그인이 성공한 이유입니다. 🎜Statement
개체 대신 PreparedStatement
개체를 사용하세요. 🎜🎜PreparedStatement
개체는 Statement
개체의 하위 클래스입니다. 미리 컴파일된 sql
이므로 Statemnet
코드보다 빠르게 실행됩니다. >더 빠르게. 🎜🎜PerpaerdStatement
는 ?
를 자리 표시자로 사용하고 setXxx(index, value)
를 사용하여 ?
에 값을 할당합니다. >🎜🎜 그럼 Statement
를 교체하고 코드를 작성해 보겠습니다. 🎜rrreee🎜테스트해 보세요: 🎜🎜🎜 성공적으로 해결되었습니다! 🎜위 내용은 SQL 삽입 문제 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!