Java基础入门day44

day44

登录功能

代码实现

DBUtil.java

package com.saas.util;
​
import java.sql.*;
​
public class DBUtil {
​
 private static final String DB_DRIVER = "com.mysql.jdbc.Driver";
 private static final String DB_URL = "jdbc:mysql://localhost:3306/saas";
 private static final String DB_USER = "root";
 private static final String DB_PASS = "Abc@1234";
​
 private static Connection conn = null;
​
 static {
     try {
         //  加载驱动,放在静态代码块中可以优先执行该驱动的加载
         Class.forName(DB_DRIVER);
     } catch (ClassNotFoundException e) {
         throw new RuntimeException(e);
     }
 }
​
 /**
     * 数据库连接对象的获取
     * @return 数据库连接对象
     */
    public static Connection getConn(){
​
        try {
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
​
        return conn;
    }
​
    /**
     * 数据库连接资源的关闭,要注意关闭的顺序
     * @param rs    //  要关闭的ResultSet对象
     * @param stmt  //  要关闭的Statement对象
     * @param conn  //  要关闭的Connection对象
     */
    public static void closeAll(ResultSet rs, Statement stmt, Connection conn){
        try {
            if(rs != null){
                rs.close();
                rs = null;
            }
            if(stmt != null){
                stmt.close();
                stmt = null;
            }
            if(conn != null){
                conn.close();
                conn = null;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

Account.java

package com.saas.entity;
​
public class Account {
​
    private int aid;
    private String name;
    private String pass;
    private double money;
​
    @Override
    public String toString() {
        return "Account{" +
                "aid=" + aid +
                ", name='" + name + '\'' +
                ", pass='" + pass + '\'' +
                ", money=" + money +
                '}';
    }
​
    public int getAid() {
        return aid;
    }
​
    public void setAid(int aid) {
        this.aid = aid;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getPass() {
        return pass;
    }
​
    public void setPass(String pass) {
        this.pass = pass;
    }
​
    public double getMoney() {
        return money;
    }
​
    public void setMoney(double money) {
        this.money = money;
    }
}

IAccountDao.java

package com.saas.dao;
​
public interface IAccountDao {
​
    /**
     * 登录方法,判断用户名密码是否匹配
     * @param name 用户名
     * @param pass 密码
     * @return 用户名和密码是否和数据库匹配
     */
    boolean login(String name, String pass);
}

AccountDaoImpl.java

package com.saas.dao.impl;
​
import com.saas.dao.IAccountDao;
import com.saas.util.DBUtil;
​
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
​
public class AccountDaoImpl implements IAccountDao{
​
    private Connection conn = null;
​
    private Statement stmt = null;
​
    private ResultSet rs = null;
​
    @Override
    public boolean login(String name, String pass) {
        boolean flag = false;
​
        conn = DBUtil.getConn();
​
        String sql = "select * from account where name = '" + name + "' and pass = '" + pass + "'";
​
        try {
            stmt = conn.createStatement();
​
            rs = stmt.executeQuery(sql);
​
            if (rs.next()){
                flag = true;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
​
        return flag;
    }
}

TestAccount.java

package com.saas.test;
​
import com.saas.dao.IAccountDao;
import com.saas.dao.impl.AccountDaoImpl;
​
import java.util.Scanner;
​
public class TestAccount {
​
    public static void main(String[] args) {
        IAccountDao iad = new AccountDaoImpl();
​
        Scanner input = new Scanner(System.in);
​
        System.out.println("请输入用户名:");
        String name = input.nextLine();
​
        System.out.println("请输入密码:");
        String pass = input.nextLine();
​
//        System.out.println(iad.login(name, "000' or 1 = 1 or '1' = '"));
        System.out.println(iad.login(name, pass));
    }
}
mysql> select * from account;
+-----+----------+--------+-------+
| aid | name     | pass   | money |
+-----+----------+--------+-------+
|   1 | wukong   | 999999 |  5000 |
|   2 | tangtang | 000000 |  6000 |
+-----+----------+--------+-------+

运行TestAccount测试类

请输入用户名:
wukong
请输入密码:
999999
true
用户名密码都正确得到true
请输入用户名:
wukong
请输入密码:
123
false
用户名密码不匹配false

这个结果看似没有问题

SQL注入

概念

用户输入的数据中含有SQL关键字或者语法并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一直得到正确的结果,这种现象被称之为SQL注入

请输入用户名:
wukong
请输入密码:
000' or 1 = 1 or '1' = '
true
用户名密码不匹配,但是也得到了true的结果,因为用户输入的输入中含有SQL关键字,导致SQL语句执行后都有结果

如何避免

由于编写SQL语句时在用户输入数据,整合后再进行编译,所以为了避免SQL注入的问题,我们要使SQL语句再用户输入数据前就已经进行编译成完整的SQL语句,再进行数据填充

JDBC中的PreparedStatement对象具备这样的功能

PreparedStatement

PreparedStatement接口继承自Statement接口,执行SQL语句的方法会更加有效

应用

作用:

预编译SQL语句,效率更高

安全,避免SQL注入

可以动态填充数据,执行多个SQL语句

实现

参数标记

String sql = "select * from account where name = ? and pass = ?";

动态绑定参数:

stmt.setXxx(index下标, 值)
参数下标从1开始,为指定参数下标绑定值
         stmt.setString(1, name);
         stmt.setString(2, pass);

执行结果

请输入用户名:
wukong
请输入密码:
000' or '1' = '1
false
即使输入了带有SQL关键字的语句,也可以保证不会有正确结果

jdbc实现事务

使用jdbc中connection对象的setAutoCommit(false)强制让连接对象不默认执行,每次都不直接执行,直到出现connection对象的commit或者rollback为止

@Override
public boolean transfer(String from, String to, double money) {
 boolean flag = false;
 try {
     conn = DBUtil.getConn();

     Account fromAccout = getAccountByName(from);
     if(fromAccout == null){
         System.out.println("请检查转出账户是否存在!");
         return  false;
     }

     Account toAccout = getAccountByName(to);
     if(toAccout == null){
         System.out.println("请检查转入账户是否存在!");
         return false;
     }

     double fromMoney = fromAccout.getMoney();

     if(fromMoney < money){
         System.out.println("请确保转出账户有足够的余额!");
         return false;
     }

     toAccout.setMoney(toAccout.getMoney() + money);
     updateAccount(toAccout);

     System.out.println(1 / 0);

     fromAccout.setMoney(fromAccout.getMoney() - money);
     updateAccount(fromAccout);


     flag = true;

     conn.commit();
 } catch (Exception e) {
     try {
         conn.rollback();
     } catch (Exception ex) {
         ex.printStackTrace();
     }
     e.printStackTrace();
 }

 return flag;
}

jdbc相对与MySQL命令框的好处是,Java中有强大的异常处理机制

在try中“尝试”正确执行所有的代码,直到最后一行都没有异常,则让连接对象进行commit操作

一旦尝试过程中出现任何问题,则Java异常处理机制将走catch代码块,则在catch代码块中进行rollback处理

由Java的异常处理机制动态自动决定到底进行哪一步操作

注意:想要实现事务处理,必须要要在同一个connection对象上操作

更安全的方式使用事务应该使用ThreadLocal保证连接对象是同一个

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/603128.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rust使用serde_json转换Value为rust中的数据类型

为了方便转换未知json数据&#xff0c;我们可以使用serde提供的value类型来进行转换&#xff0c;将json字符串转化为Value值&#xff0c;然后可以快速使用get方法来获取值&#xff1a; let json_str r#"{"name": "John","age": 30,"c…

科技控必看!让你轻松成为机器人领域达人

科技控们注意了&#xff01;你是不是经常对机器人技术充满无限的好奇&#xff0c;却又因为缺乏合适的渠道而难以深入了解和亲身体验呢&#xff1f;别担心&#xff0c;BFT机器人&#xff0c;正是你探索机器人世界的绝佳之地&#xff01; 在这里&#xff0c;你将发现一个充满惊喜…

政安晨:【Keras机器学习示例演绎】(三十九)—— 使用 FNet 进行文本分类

目录 简介 模型 设置 加载数据集 对数据进行标记 格式化数据集 建立模型 训练我们的模型 与变换器模型比较 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&…

Linux学习之高级IO

之前的内容我们基本掌握了基础IO&#xff0c;如套接字&#xff0c;文件描述符&#xff0c;重定向&#xff0c;缓冲区等知识都是文的基本认识&#xff0c;而高级IO则是指更加高效的IO。 对于应用层&#xff0c;在读写的时候&#xff0c;本质就是把数据写给OS&#xff0c;若一方…

1W 3KVDC 隔离 单输出 DC/DC 电源模块 ——TPF 系列

TPF系列提供输出稳压&#xff0c;精度高&#xff0c;对于输出电压有要求的场合特别适合&#xff0c;工业级环境温度&#xff0c;用于PCB安装的国际标准结构。此系列产品小巧&#xff0c;效率高&#xff0c;低输出纹波及提供3000V以上的直流电压隔离&#xff0c;封装有SIP和DIP可…

实测幻方新出的超强AI大模型,中文能力对比GPT4.0不落下风

目前从网上的消息来看&#xff0c;DeepSeek中文综合能力&#xff08;AlignBench&#xff09;开源模型中最强&#xff0c;与GPT-4-Turbo&#xff0c;文心4.0等闭源模型在评测中处于同一梯队。 话不多说&#xff0c;我们开测&#xff01; 1.首先我们来让他直接来一段逻辑推理【并…

Jetpack Compose三:主题和基础控件的使用

设置主题 与Android View的主题定义方式不同&#xff0c;Jetpack Compose中的主题由许多较低级别的结构体和相关API组成&#xff0c;它们包括颜色、排版和形状属性。 Theme.kt控制工程的主题&#xff0c;它是一个可组合的Compose函数 最后主题函数ComposeStudyTheme的相关设置…

安装Nox夜神模拟器关闭了HyperV后Docker运行不了怎么办?

1.背景 为了模拟真机&#xff0c;尝试安装了Nox夜神模拟器&#xff0c; 安装过程要求关闭Hyper-V。当时只是在程序安装卸载中关闭了系统服务。以为到时勾选上就好了。操作路径&#xff1a;控制面板\所有控制面板项\程序和功能\启用或关闭Windows功能\Hyper-V。 后来卸载掉了夜神…

D盘被格式化了能找回吗 d盘格式化了数据可以找回来吗

D盘作为电脑中重要的磁盘之一&#xff0c;很多用户都会将一些重要的数据保存在D盘。但在磁盘空间不足的情况下&#xff0c;或许有些用户会将其进行格式化&#xff0c;D盘被格式化了如何恢复数据&#xff1f; 如果是比较重要的数据&#xff0c;建议用户立即进行数据恢复操作&am…

Java-异常处理-定义三角形类Triangle和异常三角形IllegalTriangleException类 (1/2)

任意一个三角形&#xff0c;其任意两边之和大于第三边。当三角形的三条边不满足前述条件时&#xff0c;就表示发生了异常&#xff0c;将这种异常情况定义为IllegalTriangleException类。 自定义异常类IllegalTriangleException&#xff1a; 当三角形的三条边不满足条件&#x…

数据丢失不慌张,手机数据恢复一键解决!

如今手机已经成为我们生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;手机都扮演着重要的角色。随着使用时间的增加&#xff0c;手机数据丢失的问题也时常发生。那么手机数据恢复有哪些方法呢&#xff1f;面对这种情况&#xff0c;先不要慌张&#xff0c;本文将…

3dmax-vray6渲染器参数设置

适用于3dmax2018-2023版本 一、【公用】 小图输出大小:1500*1125&#xff0c;勾选大气、效果&#xff1b; 大图输出大小:3000*2250&#xff0c;勾选大气、效果、置换&#xff1b; 二、【vray】 小图抗锯齿类型:渐进式&#xff1b;最小细分:1&#xff0c;最大细分:100&#…

CRM(客户关系管理系统)

商机流程 为什么选择简道云CRM&#xff1f; 行业痛点 很多客户有复杂的订单成本计算方式&#xff0c;复杂多变的审批流程&#xff0c;个性化/流程化的数据结构&#xff0c;没有自定义能力就很难满足。 解决方案 在CRM套件的基础上自定义编辑/搭建了适合公司业务的CRMERP 两…

数据结构之单单单——链表

一.链表 1&#xff09;链表的概念 链表&#xff08;Linked List&#xff09;是一种物理存储结构上非连续&#xff0c;非顺序的储存结构&#xff0c;数据元素的逻辑顺序是通过链表中指针链接次序实现的。要注意&#xff0c;链表也是线性表----->但链表在物理结构上不是线性的…

安装helm

&#xff08;作者&#xff1a;陈玓玏&#xff09; 文档&#xff1a;https://helm.sh/zh/docs/intro/install/ 文档记载了几种安装方法&#xff0c;我用的是一步到位的那种&#xff0c;直接运行curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 …

python作业五

题目&#xff1a;注册登录 制作一个注册登录模块 注册&#xff1a;将用户填入的账户和密码保存到一个文件(users.bin) 登陆&#xff1a;将用户填入账户密码和users.bin中保存的账户密码进行比对,如果账户和密码完全相同 那 么登录成功&#xff0c;否则登录失败…

C语言(递归)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

win10安装.NET Framework 3.5(包括.net2.0和3.0)

打开控制面板 选择”程序” 点击”启用或关闭Windows功能“ 把.NET Framework 3.5选项勾选即可&#xff0c;若没有下载的&#xff0c;下载即可。 PS:如果下载过程出错&#xff0c;按如下流程&#xff1a; 右击”此电脑”选择“管理”&#xff0c;找到“服务和应用程序”&#x…

JAVA(三)常用类和API

目录 常用类与基础API---String String的内存结构 构造器和常用方法 字符串构建 String与其他结构间的转换 String的常用API 系列1&#xff1a;常用方法 系列2&#xff1a;查找 系列3&#xff1a;字符串截取 系列4&#xff1a;和字符/字符数组相关 系列5&#xff1a;开头…

Mac 解决外接移动硬盘(NTFS格式)无法写入的问题

文章目录 1. 问题描述2. 解决步骤 1. 问题描述 MacOS 可以识别 NTFS 格式的磁盘&#xff0c;但是默认情况下是只读模式&#xff0c;即无法向 NTFS 格式的磁盘写入数据。这是因为 NTFS 是 Windows 系统默认的文件系统格式&#xff0c;而 MacOS 对 NTFS 的写入支持是有限的。 如…
最新文章