【JDBC】笔记(3)— 提高用户登录功能的安全性 (javaSE+MySQL+JDBC)[ 应用 PreparedStatement ]

一.实现功能:

1.解决”应用Statement的登录系统”存在的SQL注入问题
2.用户信息表
+—-+———–+———-+———-+
| id | loginName | loginPwd | realName |
+—-+———–+———-+———-+
| 1 | abc | 123 | 张三 |
| 2 | wwe | 456 | 李四 |
+—-+———–+———-+———-+

二.代码实现:

import java.sql.*;
import java.util.*;

public class JDBCTest02 {
    public static void main(String[] args) {
        //初始化界面(用户输入账号和密码)
        Map<string,string> userLoginInfo = initUI();
        //&#x9A8C;&#x8BC1;&#x7528;&#x6237;&#x540D;&#x548C;&#x5BC6;&#x7801;&#xFF08;JDBC&#xFF09;
        boolean loginSuccess = login(userLoginInfo);
        //&#x663E;&#x793A;&#x7ED3;&#x679C;&#xFF1A;
        System.out.println(loginSuccess==true?"&#x767B;&#x5F55;&#x6210;&#x529F;":"&#x767B;&#x5F55;&#x5931;&#x8D25;");
    }

    /**
     * &#x9A8C;&#x8BC1;&#x7528;&#x6237;&#x767B;&#x5F55;&#x4FE1;&#x606F;&#x662F;&#x5426;&#x6B63;&#x786E;
     * @param userLoginInfo &#x7528;&#x6237;&#x767B;&#x5F55;&#x4FE1;&#x606F;
     * @return false &#x8868;&#x793A;&#x767B;&#x5F55;&#x5931;&#x8D25;&#xFF0C;true &#x8868;&#x793A;&#x767B;&#x5F55;&#x6210;&#x529F;
     */
    private static boolean login(Map<string, string> userLoginInfo) {
        //&#x6253;&#x6807;&#x8BB0;&#xFF08;&#x767B;&#x5F55;&#x7ED3;&#x679C;&#xFF09;
        boolean loginSuccess = false;

        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            //1&#x3001;&#x6CE8;&#x518C;&#x9A71;&#x52A8;
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2&#x3001;&#x83B7;&#x53D6;&#x8FDE;&#x63A5;
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode",
                    "root","888");

            //3&#x3001;&#x83B7;&#x53D6;&#x9884;&#x7F16;&#x8BD1;&#x7684;&#x6570;&#x636E;&#x5E93;&#x64CD;&#x4F5C;&#x5BF9;&#x8C61;
            //&#x4E00;&#x4E2A;&#xFF1F;&#x4EE3;&#x8868;&#x4E00;&#x4E2A;&#x5360;&#x4F4D;&#x7B26;&#xFF0C;&#x4E00;&#x4E2A;&#xFF1F;&#x63A5;&#x53D7;&#x4E00;&#x4E2A;&#x201C;&#x503C;&#x201D;
            String sql = "select * from t_user where loginName = ? and loginPwd = ? ";
            //&#x7A0B;&#x5E8F;&#x6267;&#x884C;&#x5230;&#x6B64;&#x5904;&#xFF0C;&#x4F1A;&#x53D1;&#x9001;sql&#x8BED;&#x53E5;&#x6846;&#x5B50;&#x7ED9;DBMS&#xFF0C;&#x7136;&#x540E;DBMS&#x8FDB;&#x884C;sql&#x7684;&#x7F16;&#x8BD1;
            ps = connection.prepareStatement(sql);
            //&#x7ED9;&#x5360;&#x4F4D;&#x7B26;&#x4F20;&#x503C;&#xFF08;&#x7B2C;&#x4E00;&#x4E2A;&#xFF1F;&#x4E0B;&#x6807;&#x662F;1&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#xFF1F;&#x4E0B;&#x6807;&#x662F;2&#xFF0C;JDBC&#x7684;&#x7684;&#x4E0B;&#x6807;&#x4ECE;1&#x5F00;&#x59CB;&#xFF09;
            ps.setString(1,userLoginInfo.get("loginName"));
            ps.setString(2,userLoginInfo.get("loginPwd"));

            //4&#x3001;&#x6267;&#x884C;sql
            resultSet = ps.executeQuery();

            //5&#x3001;&#x5904;&#x7406;&#x7ED3;&#x679C;&#x96C6;
            //&#x4E0D;&#x9700;&#x8981;while&#x7ED3;&#x679C;&#x96C6;&#xFF0C;&#x56E0;&#x4E3A;&#x67E5;&#x8BE2;&#x7ED3;&#x679C;&#x4E0D;&#x662F; &#x65E0; &#x5C31;&#x662F; 1&#x6761;&#x8BB0;&#x5F55;
            if (resultSet.next()){
                loginSuccess = true;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //&#x4ECE;&#x5C0F;&#x5230;&#x5927;&#x5206;&#x522B;&#x5173;&#x95ED;&#x4E09;&#x4E2A;&#x8D44;&#x6E90;
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
        //&#x6700;&#x540E;&#x8FD4;&#x56DE; &#x767B;&#x5F55;&#x7ED3;&#x679C;&#xFF08;boolean&#xFF09;
        return loginSuccess;
    }

    /**
     * &#x521D;&#x59CB;&#x5316;&#x7528;&#x6237;&#x754C;&#x9762;
     * @return &#x7528;&#x6237;&#x7684;&#x7528;&#x6237;&#x540D;&#x548C;&#x5BC6;&#x7801;&#xFF08;Map&#xFF09;
     */
    private static Map<string, string> initUI() {
        Scanner s=new Scanner(System.in);

        System.out.println("&#x7528;&#x6237;&#x540D;&#xFF1A;");
        String loginName = s.nextLine();

        System.out.println("&#x5BC6;&#x7801;&#xFF1A;");
        String loginPwd = s.nextLine();

        //&#x7528; HashMap&#xFF08;&#x952E;&#x503C;&#x5BF9;&#x7684;&#x65B9;&#x5F0F;&#xFF09;&#x5B58;&#x50A8;&#x7528;&#x6237;&#x8F93;&#x5165;&#x7684; &#x8D26;&#x53F7;&#x548C;&#x5BC6;&#x7801;
        Map<string,string> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName",loginName);
        userLoginInfo.put("loginPwd",loginPwd);

        return userLoginInfo;
    }
}
</string,string></string,></string,></string,string>

三.效果展示:

1.使用 PreparedStatement 解决了SQL注入问题:

&#x7528;&#x6237;&#x540D;&#xFF1A;
yyds
&#x5BC6;&#x7801;&#xFF1A;
yyds' or '1'='1
&#x767B;&#x5F55;&#x5931;&#x8D25;

Process finished with exit code 0

2.注意:

1)JDBC代码部分的第三步 — 获取预编译的数据库操作对象(不同于Statement):

先写好sql语句模型:

String sql = "select * from t_user where loginName = ? and loginPwd = ? ";

发送sql语句框子给DBMS,然后DBMS准备进行sql的编译:

ps = connection.prepareStatement(sql);

给占位符传值:?的值为String就setString,?的值为int就setInt …

ps.setString(1,userLoginInfo.get("loginName"));
ps.setString(2,userLoginInfo.get("loginPwd"));

四.Statement 与 PreparedStatement 对比:

1.Statement 编译一次执行一次,PreparedStatement 编译一次,可执行n次,所以 PreparedStatement 效率较高;

2.PreparedStatement 比 Statement 更加安全;

3.Statement 可以完成根据用户的意愿,通过输入sql语句来实现相应的功能,比如:升序(asc)/降序(desc):

1)假设使用 PreparedStatement:

用户想通过按”账号首字母”升序的方式看到用户的信息,所以向?传入”asc”,但这样运行是会报错的,因为实际执行的sql语句是:
select * from t_user order by loginName ‘asc’ //那这俩单引号是什么鬼嘛,执行肯定报错啊,所以这时只能选择 Statement

String sql = "select * from t_user order by loginName ?";
ps = connection.prepareStatement(sql);
ps.setString(1,"asc");
resultSet = ps.executeQuery();

2)假设使用 Statement:

statement = connection.createStatement();
String sql = "select * from t_user order by loginName asc";
resultSet = statement.executeQuery(sql);
    while (resultSet.next()) {
    System.out.println(resultSet.getString("loginName"));
}

这样就可以根据 loginName 首字母大小升序的方式来输出 loginName:

abc
wwe

Process finished with exit code 0

Original: https://www.cnblogs.com/Burning-youth/p/15755229.html
Author: 猿头猿脑的王狗蛋
Title: 【JDBC】笔记(3)— 提高用户登录功能的安全性 (javaSE+MySQL+JDBC)[ 应用 PreparedStatement ]

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/507904/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球