JDBC SQL injection and transactions

First, prepare the database data, and fill in the data in the database.

Independent abstract method, reuse.

First, initialize the interface (define a method)
Second, verify the user name and password (define another method)
package com.bjpowernode.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

import com.mysql.*;
public class user_login {

    public static void main(String[] args) {
        //Initialization interface
        Map<String, String> userLoginInfoMap=initUI();
        //Verify user name and password
        boolean loginSuccess=login(userLoginInfoMap);
        //Output result
        System.out.println(loginSuccess?"Login successfully":"Login failed");
    }
    private static boolean login(Map<String, String> userLoginInfoMap) {
        //Mark in advance
        boolean loginsucess=false;
        String loginName=userLoginInfoMap.get("loginName");
        String loginPwd=userLoginInfoMap.get("loginPwd");
        Connection conn=null;
        Statement stmt=null;
        ResultSet rs=null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "333");
            stmt=conn.createStatement();
            String sql="select * from t_user where uname='"+loginName+"' and password='"+loginPwd+"'";
            rs=stmt.executeQuery(sql);
            if(rs.next()) {
                loginsucess=true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(rs!=null) {
                try {
                    rs.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(stmt!=null) {
                try {
                    stmt.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null) {
                try {
                    conn.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        return loginsucess;
    }
    /**
     * Initialize user interface
     * @return Login information such as user name and password entered by the user
     */
    private static Map<String, String> initUI() {
        Scanner scanner=new Scanner(System.in);
        System.out.println("User name:");
        String loginName=scanner.nextLine();
        
        System.out.println("Password:");
        String loginPwd=scanner.nextLine();
        
        Map<String, String> userLoginInfoMap=new HashMap<>();
        userLoginInfoMap.put("loginName", loginName);
        userLoginInfoMap.put("loginPwd", loginPwd);
        return userLoginInfoMap;
    }
}

But at this time, when input
User name: fdsa
Password: fdsa 'or' 1 '='1
When logging in, it will also show success. This phenomenon is called SQL injection, which is often used by hackers.
Because at this time, the sql statement becomes: select * from t_user where uname ='fdsa 'and password ='fdsa' or '1' = 'the data entered by the user participates in the compilation of the sql statement, which causes the original meaning of the sql statement to be distorted.

How to solve it?
Statement has a sub interface, PreparedStatement precompiled database operation object
It compiles the framework of sql statement in advance, and then can only pass value to sql statement, but can't modify the original meaning of sql statement.

At this time, the statement in try is written in this way, and the sql is precompiled to prevent sql injection.

Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
//The framework of sql statement, where? Represents a placeholder and a placeholder will receive a "value". Note that placeholders cannot be enclosed in single quotation marks.
String sql="select * from t_user where uname=? and password=?";
//When the program is executed here, it will send the framework of sql statement to DBMS for pre compilation of sql statement.
ps=conn.prepareStatement(sql);
//Pass value to placeholder (the first subscript is 1, and the subscript in JDBC starts from 1)
ps.setString(1, username);
ps.setString(2, password);
rs=ps.executeQuery();
if(rs.next()) {
    result=true;
}

In general, PreparedStatement is used for value transfer with high efficiency and good security. When you need to use sql injection function, you still need to use statement. For example, on JD, you can sort in ascending order

About affairs
Main statement:

Turn off automatic transaction commit

conn.setAutoCommit(false);

Submission of affairs

conn.commit();

Transaction rollback on exception
The statement may generate an exception, which is thrown in the function header

conn.rollback();
package JDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class test {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "333");
            // Turn off automatic transaction commit
            conn.setAutoCommit(false);
            String sql = "update t_act set balance=? where actno=?";
            ps = conn.prepareStatement(sql);
            ps.setDouble(1, 10000);
            ps.setInt(2, 111);
            int count = ps.executeUpdate();
            ps.setDouble(1, 10000);
            ps.setInt(2, 222);
            count += ps.executeUpdate();
            System.out.println(count == 2 ? "Successful transfer" : "Transfer failure");
            // Submission of affairs
            conn.commit();
        } catch (Exception e) {
            // Transaction rollback on exception
            // The statement may generate an exception, which is thrown in the function header
            conn.rollback();
            e.printStackTrace();
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

}

Keywords: Java SQL JDBC MySQL

Added by shatztal on Wed, 30 Oct 2019 09:32:06 +0200