• 解决SQL注入问题


    解决SQL注入问题

    1. /**
    2. * 作者:杜聚宾
    3. *
    4. * 1、解决SQL注入问题?
    5. * 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
    6. * 即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译,不起作用。
    7. * 要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
    8. * PreparedStatement接口继承了java.sql.Statement
    9. * PreparedStatement是属于预编译的数据库操作对象。
    10. * PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传“值”。
    11. * 2、测试结果:
    12. * 用户名:fdas
    13. * 密码:fdsa' or '1'='1
    14. * 登录失败
    15. * 3、解决SQL注入的关键是什么?
    16. * 用户提供的信息中即使含有sql语句的关键字,但是这些关键字并没有参与编译。不起作用。
    17. * 4、对比一下Statement和PreparedStatement?
    18. * - Statement存在sql注入问题,PreparedStatement解决了SQL注入问题。
    19. * - Statement是编译一次执行一次。PreparedStatement是编译一次,可执行N次。PreparedStatement效率较高一些。
    20. * - PreparedStatement会在编译阶段做类型的安全检查。
    21. *
    22. * 综上所述:PreparedStatement使用较多。只有极少数的情况下需要使用Statement
    23. * 5、什么情况下必须使用Statement呢?
    24. * 业务方面要求必须支持SQL注入的时候。
    25. * Statement支持SQL注入,凡是业务方面要求是需要进行sql语句拼接的,必须使用Statement。
    26. */
    27. public class JDBCTest07 {
    28. public static void main(String[] args) {
    29. // 初始化一个界面
    30. Map userLoginInfo = initUI();
    31. // 验证用户名和密码
    32. boolean loginSuccess = login(userLoginInfo);
    33. // 最后输出结果
    34. System.out.println(loginSuccess ? "登录成功" : "登录失败");
    35. }
    36. /**
    37. * 用户登录
    38. * @param userLoginInfo 用户登录信息
    39. * @return false表示失败,true表示成功
    40. */
    41. private static boolean login(Map userLoginInfo) {
    42. // 打标记的意识
    43. boolean loginSuccess = false;
    44. // 单独定义变量
    45. String loginName = userLoginInfo.get("loginName");
    46. String loginPwd = userLoginInfo.get("loginPwd");
    47. // JDBC代码
    48. Connection conn = null;
    49. PreparedStatement ps = null; // 这里使用PreparedStatement(预编译的数据库操作对象)
    50. ResultSet rs = null;
    51. try {
    52. // 1、注册驱动
    53. Class.forName("com.mysql.jdbc.Driver");
    54. // 2、获取连接
    55. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "333");
    56. // 3、获取预编译的数据库操作对象
    57. // SQL语句的框子。其中一个?,表示一个占位符,一个?将来接收一个“值”,注意:占位符不能使用单引号括起来。
    58. String sql = "select * from t_user where loginName = ? and loginPwd = ?";
    59. // 程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的预先编译。
    60. ps = conn.prepareStatement(sql);
    61. // 给占位符?传值(第1个问号下标是1,第2个问号下标是2,JDBC中所有下标从1开始。)
    62. ps.setString(1, loginName);
    63. ps.setString(2, loginPwd);
    64. // 4、执行sql
    65. rs = ps.executeQuery();
    66. // 5、处理结果集
    67. if(rs.next()){
    68. // 登录成功
    69. loginSuccess = true;
    70. }
    71. } catch (Exception e) {
    72. e.printStackTrace();
    73. } finally {
    74. // 6、释放资源
    75. if (rs != null) {
    76. try {
    77. rs.close();
    78. } catch (SQLException e) {
    79. e.printStackTrace();
    80. }
    81. }
    82. if (ps != null) {
    83. try {
    84. ps.close();
    85. } catch (SQLException e) {
    86. e.printStackTrace();
    87. }
    88. }
    89. if (conn != null) {
    90. try {
    91. conn.close();
    92. } catch (SQLException e) {
    93. e.printStackTrace();
    94. }
    95. }
    96. }
    97. return loginSuccess;
    98. }
    99. /**
    100. * 初始化用户界面
    101. * @return 用户输入的用户名和密码等登录信息
    102. */
    103. private static Map initUI() {
    104. Scanner s = new Scanner(System.in);
    105. System.out.print("用户名:");
    106. String loginName = s.nextLine();
    107. System.out.print("密码:");
    108. String loginPwd = s.nextLine();
    109. Map userLoginInfo = new HashMap<>();
    110. userLoginInfo.put("loginName", loginName);
    111. userLoginInfo.put("loginPwd", loginPwd);
    112. return userLoginInfo;
    113. }
    114. }

  • 相关阅读:
    Review of Matrix Theory (HITSZ) 含22年真题
    C++征途 --- STL中的常用算法(下)
    解决ffmpeg的播放摄像头的延时优化问题(项目案例使用有效)
    RPA自动化全平台文章同步助手
    西门子HMI切换页面时的指示功能
    行列式、逆矩阵、列空间和零空间(3Blue1Brown学习笔记)
    ARMv8内存模型
    Spark 的主要组件及任务分工
    后端面试话术集锦第 十五 篇:java线程面试话术
    Java之面向对象中
  • 原文地址:https://blog.csdn.net/weixin_52385232/article/details/126799119