【Mysql】JDBC从放弃到入门(中)


【Mysql】JDBC从放弃到入门(上)
【Mysql】JDBC从放弃到入门(中)
【Mysql】JDBC从放弃到入门(下)

1.项目的业务需求

程序运行的时候,提供一个输入的入口,可以让用户输入用户名的密码,用户输入用户名和密码的时候,提交信息,Java程序收集用户信息,Java程序连接数据库验证用户名和密码是否合法。合法,显示登录成功,不合法,显示登录失败。

2.数据库设计

我们使用powerDesigner来设计数据库。

2.1填写Table Properties

在这里插入图片描述
生成用户表:
在这里插入图片描述

2.2生成sql语句

在这里插入图片描述

2.3保存项目和sql语句

保存项目后缀名为 pdm,保存sql语句后缀名为 sql。
在这里插入图片描述

2.4执行sql语句

我们在开始启动项目的时候,会得到一个后缀名为.sql文件,我们需要将sql语句导入数据库中。我们可以使用:

source + sql语句地址

在这里插入图片描述

在这里插入图片描述
于是得到:
在这里插入图片描述

3.实现

3.1用户界面初始化

package com.sdnu;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @author Beyong
 * @Description JdbcTest5
 * @date 2021/07/19 12:52
 */
public class JdbcTest5 {
    public static void main(String[] args) {
        Map<String, String> userLoginInfo = initUI();
    }
    private static Map<String, String> initUI(){
        Scanner user = new Scanner(System.in);
        System.out.println("Please input userName: ");
        String userName = user.next();
        System.out.println("Please input password: ");
        String passWord = user.next();
        Map<String, String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("userName", userName);
        userLoginInfo.put("passWord", passWord);
        return userLoginInfo;
    }
}

3.2登录方法实现

package com.sdnu;

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

/**
 * @author Beyong
 * @Description JdbcTest5
 * @date 2021/07/19 12:52
 */
public class JdbcTest5 {
    public static void main(String[] args) {
        Map<String, String> userLoginInfo = initUI();
        boolean loginSucceed = login(userLoginInfo);
        System.out.println(loginSucceed ? "登录成功" : "登录失败");
    }
    private static boolean login(Map<String, String> userLoginInfo) {
        boolean loginSucceed = false;
        Connection conn;
        Statement stmt = null;
        ResultSet rs = null;
        try{
            //1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?" +
                    "useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&" +
                    "allowMultiQueries=true&serverTimezone=Asia/Shanghai","root",
                    "123");
            //3.获取数据库操作对象
            stmt = conn.createStatement();
            //4.执行sql语句
            String sql = "SELECT * FROM t_user WHERE loginName = '"+userLoginInfo.get("userName")+"' AND loginPwd = '"+userLoginInfo.get("passWord")+"'";
            rs = stmt.executeQuery(sql);
            //5.处理查询结果
            if(rs.next()){
                loginSucceed = true;
            }
            return loginSucceed;
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }catch(SQLException e){
            e.printStackTrace();
        }finally{
            //6.释放资源
            if( rs != null ){
                try{
                    rs.close();
                }catch(SQLException e) {
                    e.printStackTrace();
                }
            }
            if( stmt != null){
                try{
                    stmt.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
        return loginSucceed;
    }
    private static Map<String, String> initUI(){
        Scanner user = new Scanner(System.in);
        System.out.println("Please input userName: ");
        String userName = user.next();
        System.out.println("Please input password: ");
        String passWord = user.next();
        Map<String, String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("userName", userName);
        userLoginInfo.put("passWord", passWord);
        return userLoginInfo;
    }
}

先在数据库中写入一些信息,然后测试。
在这里插入图片描述
在这里插入图片描述

4.sql注入

4.1sql注入问题

在这里插入图片描述
我随便写了一段话(当然不是太随便的),没想到还通过了,其实,这就是注入,这是黑客攻击使用的一种手段。

我们通过设立断点+debug来查找原因:
在这里插入图片描述
在这里插入图片描述
仔细观察下面的sql语句:
在这里插入图片描述
发现语句的意思改变了,后面加上了or ‘1’ = ‘1’,这当然永远为真。

来看一段简书上的解释:
在这里插入图片描述

4.2解决sql注入问题

解决思路:用户提供的信息不参与sql语句的编译。
使用java.sql.PreparedStatement

PreparedStatement接口继承java.sql.Statement
PreparedStatement是预编译对象。
PreparedStatement的原理是:先对sql语句的框架进行编译,然后再给sql语句传值。

package com.sdnu;

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

/**
 * @author Beyong
 * @Description 解决注入问题
 * @date 2021/07/19 18:56
 */
public class JdbcTest6 {

    public static void main(String[] args) {
        Map<String, String> userLoginInfo = initUI();
        boolean loginSucceed = login(userLoginInfo);
        System.out.println(loginSucceed ? "登录成功" : "登录失败");
    }
    private static boolean login(Map<String, String> userLoginInfo) {
        boolean loginSucceed = false;
        Connection conn;
        PreparedStatement ps = null;
        ResultSet rs = null;
        String loginName = userLoginInfo.get("userName");
        String loginPwd = userLoginInfo.get("passWord");
        try{
            //1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?" +
                            "useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&" +
                            "allowMultiQueries=true&serverTimezone=Asia/Shanghai","root",
                    "123");
            //3.获取数据库操作对象
            //其中一个?表示一个占位符,一个?将来只能传一个值,?不能使用引号引起来。
            String sql = "SELECT * FROM t_user WHERE loginName = ? AND loginPwd = ? ";
            //程序执行下面一条语句会将sql语句传给DBMS,然后DBMS对sql语句进行编译。
            ps = conn.prepareStatement(sql);
            //给占位符传值,jdbc的值下标从1开始。
            ps.setString(1,loginName);
            ps.setString(2,loginPwd);
            //4.执行sql语句
            rs = ps.executeQuery();
            //5.处理查询结果
            if(rs.next()){
                loginSucceed = true;
            }
            return loginSucceed;
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }catch(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();
                }
            }
        }
        return loginSucceed;
    }
    private static Map<String, String> initUI(){
        Scanner user = new Scanner(System.in);
        System.out.println("Please input userName: ");
        String userName = user.next();
        System.out.println("Please input password: ");
        String passWord = user.next();
        Map<String, String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("userName", userName);
        userLoginInfo.put("passWord", passWord);
        return userLoginInfo;
    }
}

在这里插入图片描述

4.3Statement和PreparedStatement的使用

PreparedStatement使用不需要注入的地方,Statement使用在需要注入的地方,比如我们使用淘宝网站的时候,有一个升序和降序按钮,它就需要注入。

在这里插入图片描述

作者:Beyong    
出处:Beyong博客
github地址:https://github.com/beyong2019

本博客中未标明转载的文章归作者Beyong有,欢迎转载,但未经作者同意必须保留此段声明,且在文章明显位置给出原文连接,否则保留追究法律责任的权利。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值