SQLインジェクションとは
ログインインターフェイスを作成し、パスワードをfdsaと1に設定します。コードは、次のとおりです。
select * from tbl_user where username = 'fdsafds' and password = 'fdsa' or '1'='1';
入ると
用户名:fdsafds
密码:fdsa' or '1'='1
这样可以登录成功,为什么?
条件が常に確立され、データベーステーブル内のすべてのデータがクエリされる上記のSQLステートメント
上記の現象はSQLインジェクションと呼ばれます。
当用户提供的信息当中含有SQL语句的关键字,并且这些关键字参与了SQL语句的编译过程,导致原先的SQL语句原意被扭曲。
根本原因:先拼接SQL语句,再进行编译,这是根本原因。
SQLインジェクションをどのように見るか
SQLインジェクションは必ずしも危険ではありませんが、ほとんどの場合、システムのセキュリティを危険にさらします。システムの一部の特殊機能でもSQLインジェクションが必要になる場合があります。
現時点でSQLインジェクションをサポートするには、java.sql.Statementインターフェースを使用する必要があります。
SQLインジェクションを解決する方法、またはSQLインジェクションを防ぐ方法は?
java.sql.PreparedStatementは、プリコンパイルされたデータベース操作オブジェクトと呼ばれ、SQLインジェクションを防ぐことができます。
原則:
对SQL语句框架进行预先编译,再接收用户提供的信息,即使提供的信息当中含有SQL语句的关键字,但是这些关键字并没有参与SQL语句的编译,
那么它也只是一个普通的字符串,SQL语句原意不会被扭曲,防止了SQL注入。
PreparedStatementは、Statementのサブインターフェースです。
ほとんどの場合、SQLインジェクションを防ぐ必要があるため、PreparedStatementがより多く使用されます。
StatementとPreparedStatementの違い
1. Statement是先进行SQL语句拼接,再进行SQL语句的编译,存在SQL注入问题;
2. PreparedStatement是预先编译SQL语句框架(带有占位符的SQL),然后再给占位符赋值,防止SQL注入;
3. Statement编译一次,执行一次,编译一次,执行一次,PreparedStatement编译一次框架,执行N次,
4. PreparedStatement效率较高。
バッチ処理のための事前コンパイル
100以上のデータを処理する必要がある場合、元の処理方法を使用すると、次のようになります。
for(int i=1;i<=100;i++){
String sql="insert into dept(deptno,dname,loc) values("+i+",'dept_"+i+"','北京')";
ps.executeUpdate(sql);
}
次の問題が発生する可能性があります。
-
SQLコマンドの記述の問題:
各SQLステートメントが異なるデータを確実に伝送するために、文字列スプライシングメソッド
"insert into dept(deptno、dname、loc)values(" + i + "、 'dept _" + i + "'、 'Beijing' ) "; -
時間の浪費:PreparedStatementオブジェクトは、一度に1つのSQLコマンドしかプッシュできません。
100個のSQLコマンドをプッシュするには、100回のラウンドトリップが必要であり、多くの時間を浪費します。
ご覧のとおり、上記のプログラムはプログラマー
にとって恐ろしいものです。この種のバッチ処理の問題では、コンパイル済みのSQLコマンドの形式を取ります。
"?"是占位符,一个问号代替一个值
预编译SQL相当一个模具,在后续开发时,只需要将数据填充到占位符,就可以得到一个全新SQL
String sql ="insert into dept(deptno,dname,loc) values(?,?,?)";
//注册Driver
Class.forName("com.mysql.jdbc.Driver");
//建立通道
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "123");
//【建立交通工具时,需要将预编译SQL命令注册到PreparedStatement】
PreparedStatement ps = con.prepareStatement(sql);
//プリコンパイルされたSQLコマンドにデータを入力して、まったく新しいSQLコマンドを生成します
//4.向MySql服务器推送100条数据
for(int i=1;i<=100;i++){
ps.setInt(1, i); //inser into dept (deptno,dname,loc) values(1,?,?)
ps.setString(2, "dept_"+i); //inser into dept (deptno,dname,loc) values(1,'dept_1',?)
ps.setString(3, "北京");//inser into dept (deptno,dname,loc) values(1,'dept_1','北京')
//在新的SQL语句生成之后,将SQL语句作为子弹添加到PS的弹夹
ps.addBatch(); //[sql1,sql2,...]
}
JavaのStatement.addBath()メソッドは、指定されたSQLコマンドをこのStatementオブジェクトの現在のコマンドリストに追加します。このリストのコマンドは、executeBatchメソッドを呼び出すことでバッチで実行できます。
[1回限り] psを介して実行するために100個のSQLステートメントをmysqlサーバーにプッシュします
ps.executeBatch(); // 推送100条SQL命令只需要往返一次
次に、前に作成したリソースを閉じることができます。