Statement和PreparedStatement

使用用户登录例子来区别Statement和PreparedStatement

需要使用Statement的例子在这里

import java.util.HashMap;
import java.sql.*;
import java.util.Map;
import java.util.Scanner;
/**
 * 用户名:fdsa
 * 密码:fdsa' or '1'='1
 * 用Statement输入以上会登录成功
 * 这种现象被称为SQL注入(安全隐患)
 * 1.导致SQL注入的根本原因是什么?
 *   	用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程,导致sql语句的原意被扭曲,进而形成SQL注入
 * 2.如何解决SQL注入问题?
 *   	只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
 *   	要想用户信息不参加SQL语句的编译,那么必须使用java.sql.PreparedStatement
 *   	PreparedStatement接口继承了java.sql.Statement 它是属于预编译的数据库操作对象
 *   它的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传值
 * 3.对比Statement和PreparedStatement
 *   	-Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题
 *   	-Statement是编译一次执行一次。PreparedStatement是编译一次可以执行n次
 *   	-PreparedStatement会在编译阶段做类型的安全检查
 *   综上所述:PreparedStatement使用较多,只有极少数的情况下需要使用Statement
 * 4.什么情况下必须使用Statement?
 * 		Statement支持SQL注入,凡是业务方面要求是需要进行sql语句拼接,必须使用Statement。
 * 		例如用户在控制台输入desc变为降序,输入asc变为升序 
 */
public class LoginTest {
	public static void main(String[] args) {
		//初始化用户界面
		Map<String,String> userLoginInfo = initUI();
		//验证用户名和密码
		boolean loginSuccess = login(userLoginInfo);
		//输出最后结果
		System.out.println(loginSuccess ? "登录成功" : "登录失败");
		
	}
	/**
	 * 用户登录
	 * @param userLoginInfo 用户登录信息
	 * @return false表示失败 true表示成功
	 */
	private static boolean login(Map<String, String> userLoginInfo) {
		// TODO Auto-generated method stub
		boolean loginSuccess = false;
		String loginName = userLoginInfo.get("loginName");
		String loginPwd = userLoginInfo.get("loginPwd");
		Connection conn = null;
		//Statement sm = null; 改为PreparedStatement
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user","root","123456");
			//sm = conn.createStatement();
			//String sql = "select * from user where loginName = '"+loginName+"'and loginPwd = '"+loginPwd+"'";
			//获取预编译的数据库操作对象  ?表示一个占位符,将来接受一个值
			String sql = "select * from user where loginName = ? and loginPwd = ?";//SQL语句框架
			ps = conn.prepareStatement(sql);
			//程序执行到此处,会发送sql语句框架给DBMS,然后DBMS进行sql语句的预先编译。
			//给占位符?传值(第一个问号下标是1,第二个是2)
			ps.setString(1, loginName);
			ps.setString(2, loginPwd);
			rs = ps.executeQuery();//此处就不用传入sql语句了
			if(rs.next()) {
				loginSuccess = true;
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(rs != null) {
					rs.close();
				}
			}catch(SQLException e) {
				e.printStackTrace();
			}
			try {
				if(ps != null) {
					ps.close();
				}
			}catch(SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn != null) {
					conn.close();
				}
			}catch(SQLException e) {
				e.printStackTrace();
			}
		}
		return loginSuccess;
	}
	/**
	 * 初始化用户界面
	 * @return 用户输入的用户名和密码等登录信息
	 */
	private static Map<String, String> initUI() {
		// TODO Auto-generated method stub
		Scanner tf = new Scanner(System.in);
		System.out.println("用户名:");
		String loginName = tf.nextLine();
		System.out.println("密码:");
		String loginPwd = tf.nextLine();
		Map<String,String> userLoginInfo = new HashMap<String,String>();
		userLoginInfo.put("loginName", loginName);
		userLoginInfo.put("loginPwd", loginPwd);
		return userLoginInfo;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值