使用mysql版本:

Ver 8.0.21 for Win64 on x86_64 (MySQL Community Server – GPL)

jdk版本:

Java(TM) SE Runtime Environment (build 1.8.0_121-b13)

实现功能

/**
 * 实现功能:
 *  1、需求:
 *      模拟用户登录功能的实现
 *  2、业务描述:
 *      程序运行的时候,提供一个输入的入口,可以提交用户输入用户名和密码,
 *      提交信息,java程序收集到用户信息,java程序连接到数据库判断验证
 *      用户名和密码是否合法
 *          合法:登录成功
 *          不合法:登录失败
 *  3、数据准备:
 *      实际开发中,表的设计会使用到专业的建模工具,如:PowerDesigner
 */

JDBCTestLogin.class

package top.djosimon.jdbc;

import java.sql.*;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Scanner;

/**
 * 未使用预编译数据库操作对象,可能存在sql注入问题。(高版本数据库可能不存在这个问题)
 *
 * @author : dj
 * @date : 2020/10/16
 */
public class JDBCTestLogin {
    public static void main(String[] args) {
        // 初始化一个用户界面,用以返回用户输入的登录名和密码等信息
        HashMap<String, String> userInfo = loginUI();
        // 执行登录,验证用户名和密码的正确性
        boolean loginSuccess = login(userInfo);
        // 登录失败/成功
        System.out.println(loginSuccess ? "登录成功" : "登录失败");
    }

    /**
     * 登录方法
     *
     * @param userInfo 用户的登录信息
     * @return false--登陆失败、true--登录成功
     */
    private static boolean login(HashMap<String, String> userInfo) {
        // JDBC代码
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;

        // 数据库连接相关信息
        String userName = userInfo.get("userName");
        String userPwd = userInfo.get("userPwd");
        ResourceBundle bundle = ResourceBundle.getBundle("top.djosimon.jdbc.jdbcTest");
        String driver = bundle.getString("driver");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");

        // 默认false,用户输入了正确的用户名和密码,则置为true
        boolean loginSuccess = false;

        try {
            // 1、注册驱动(利用反射机制)
            Class.forName(driver);
            // 2、获取数据库连接
            conn = DriverManager.getConnection(url, user, password);
            // 3、获取数据库操作对象
            stat = conn.createStatement();
            // 4、执行sql语句
            String sql = "select * from t_user where loginName='" + userName + "' and loginPwd='" + userPwd + "'";
            rs = stat.executeQuery(sql);
            // 5、处理查询结果集
            if (rs.next()) {
                // 登录成功
                loginSuccess = true;
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 6、释放资源、关闭连接
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stat != null) {
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return loginSuccess;
    }

    /**
     * 用户登录界面,提示用户进行用户名、密码的输入,进行登录操作
     *
     * @return 将用户输入的用户名、密码封装到一个map集合当中,并返回。
     */
    private static HashMap<String, String> loginUI() {
        Scanner scan = new Scanner(System.in);
        System.out.print("用户名:");
        String userName = scan.nextLine();
        System.out.print("密码:");
        String userPwd = scan.nextLine();
        HashMap<String, String> userInfo = new HashMap<>();
        userInfo.put("userName", userName);
        userInfo.put("userPwd", userPwd);
        return userInfo;
    }
}

用户输入(其中包含了sql语句的关键字,关键字参与了编译):

用户名:admin

密码:admin’ or ‘1’=’1

可能存在sql注入的安全隐患!

JDBCTestLogin2.class

package top.djosimon.jdbc;

import java.sql.*;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Scanner;

/**
 * 使用预编译的数据库操作对象,解决了sql注入的问题。
 *
 * @author : dj
 * @date : 2020/10/16
 */
public class JDBCTestLogin2 {
    public static void main(String[] args) {
        // 初始化用户界面
        HashMap<String, String> userInfo = loginUI();
        // 执行登录
        boolean loginSuccess = login(userInfo);
        // 输出登录结果
        System.out.println(loginSuccess ? "登录成功" : "登录失败");
    }

    /**
     * 用户登录
     *
     * @param userInfo 用户输入的登录信息
     * @return 返回值false:登录失败,true:登录成功
     */
    private static boolean login(HashMap<String, String> userInfo) {
        boolean loginSuccess = false;
        // JDBC代码
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        // 连接数据库相关信息
        ResourceBundle bundle = ResourceBundle.getBundle("top.djosimon.jdbc.JDBCTest");
        String driver = bundle.getString("driver");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");
        // 用户相关信息
        String userName = userInfo.get("userName");
        String userPwd = userInfo.get("userPwd");
        try {
            // 1、注册驱动
            Class.forName(driver);
            // 2、获取连接
            conn = DriverManager.getConnection(url, user, password);
            // 3、获取预编译的数据库操作对象
            // 其中一个“?”表示一个占位符,一个“?”接收一个值。注意:占位符“?”不可用单引号括起来。
            String sql = "select * from t_user where loginName = ? and loginPwd = ?"; // sql语句的框架
            // ●●●程序执行到此步,会发送sql语句的框架给DBMS,然后DBMS进行sql语句的预先编译。
            ps = conn.prepareStatement(sql);
            // 给占位符?传值(第一个问号下标是1,第二个问号下标是2,JDBC中所有下标从1开始。)
            ps.setString(1, userName);
            ps.setString(2, userPwd);
            // 4、执行sql
            rs = ps.executeQuery();
            // 5、处理查询结果集
            if (rs.next()) {
                // 登录成功
                loginSuccess = true;
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 6、释放资源,关闭连接
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return loginSuccess;
    }

    /**
     * 用户登录界面
     *
     * @return 返回用户输入的用户名、密码等信息
     */
    private static HashMap<String, String> loginUI() {
        Scanner scan = new Scanner(System.in);
        System.out.println("用户名:");
        String userName = scan.nextLine();
        System.out.println("密码:");
        String userPwd = scan.nextLine();
        HashMap<String, String> userInfo = new HashMap();
        userInfo.put("userName", userName);
        userInfo.put("userPwd", userPwd);
        return userInfo;
    }

}

解决了sql注入的问题。

用户提供的信息中即使含有sql语句的关键字,但这些关键字并没有参与编译,不起作用。

jdbcTest.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/learn?serverTimezone=UTC
user=root
password=123456

分类: Java

Deng Jia

Keep Moving.

0 条评论

发表评论

电子邮件地址不会被公开。