登录实践操作
/*
1.会出现SQL注入操作
2.测试结果
用户名:fff
密码:fff' or '1'='1
登录成功
*/
public class JDBCTest01{
public static void main(String[] args){
//初始化一个界面
Map<String,String> userLoginInfo = initUI();
//验证用户名和密码
boolean loginSuccess = login(userLoginInfo);
//最后输出结果
System.out.println(loginSuccess ? "登陆成功" : "登录失败");
}
/*
用户登录
userLoginInfo 用户登录信息
return false表示失败 true表示成功
*/
pricate static boolean login(Map<String,String> userLoginInfo){
//打标记的意识
boolean loginSuccess = false;
//单独定义变量
String loginName = userLoginInfo.get("loginName");
String loginPwd = userLoginInfo.get("loginPwd");
//JDBC代码
Connection conn = null;
Statement stmt = null;//使用PreparedStatement(预编译的数据库操作对象)
ResultSet re = null;
try{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver"); //2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
//3.获取与编译的数据库操作对象
stmt = conn.createStatement();
//4.执行SQL
String sql = "select * from t_user where loginName = '"+loginName+"' and loginPwd = '"+loginPwd+"' ";
re = stmt.executeQuery(sql);
//5.处理结果集
if(re.next()){
//登录成功
loginSuccess = true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
//6.释放资源
if(re!=null){
try{
re.close();
}
catch(Exception e){
e.printStackTrace();
}
}
if(stmt!=null){
try{
stmt.close();
}
catch(Exception e){
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
private static Map<String,String> initUi(){
Scanner s = new Scanner(System.in);
System.out.print("用户名:");
String loginName = s.nextLine();
System.out.print("密码:");
String loginPwd = s.nextLine();
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}
SQL注入解决方法
/*
1.解决SQL注入问题
只要用户提供的信息不参与SQL语句的编译过程,问题就解决了
即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译
要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
PreparedStatement接口继承了java.sql.Statement
PreparedStatement是属于预编译的数据库操作对象
PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传"值"
2.测试结果
用户名:fff
密码:fff' or '1'='1
登录失败
3.解决SQL注入的关键是:
用户提供的信息中即使含有SQL语句的关键字,但是这些关键字并没有参与编译,不起作用
4.PreparedStatement和Statement区别
Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题
Statement是编译一次执行一次,PreparedStatement是编译一次,可执行N次,PreparedStatement效率较高一些
PreparedStatement会在编译阶段做类型的安全检查
5.什么情况下必须使用Statement?
业务方面要求必须支持SQL注入的时候
Statement支持SQL注入,凡是业务方面要求是需要进行SQL语句拼接的,必须使用Statement
*/
public class JDBCTest01{
public static void main(String[] args){
//初始化一个界面
Map<String,String> userLoginInfo = initUI();
//验证用户名和密码
boolean loginSuccess = login(userLoginInfo);
//最后输出结果
System.out.println(loginSuccess ? "登陆成功" : "登录失败");
}
/*
用户登录
userLoginInfo 用户登录信息
return false表示失败 true表示成功
*/
pricate static boolean login(Map<String,String> userLoginInfo){
//打标记的意识
boolean loginSuccess = false;
//单独定义变量
String loginName = userLoginInfo.get("loginName");
String loginPwd = userLoginInfo.get("loginPwd");
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;//使用PreparedStatement(预编译的数据库操作对象)
ResultSet re = null;
try{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver"); //2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
//3.获取与编译的数据库操作对象
//SQL语句的框子 其中一个 ? 代表一个占位符,一个 ? 将来接收一个"值",注意:占位符不能使用单引号括起来
String sql = "select * from t_user where loginName = ? and loginPwd = ? ";
//程序执行到此处,会发送SQL语句框子给DBMS,然后DBMS进行SQL语句的预先编译
ps = conn.prepareStatement(sql);
//给占位符 ? 传值(第一个问号下标为1,第二个问号下标为2,JDBC中所有下标从1开始)
ps.setString(1,loginName);
ps.setString(2,loginPwd);
//4.执行SQL
re = ps.escuteQuery()//SQL语句已经预先编译,不需要再插入SQL语句
//5.处理结果集
if(re.next()){
//登录成功
loginSuccess = true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
//6.释放资源
if(re!=null){
try{
re.close();
}
catch(Exception e){
e.printStackTrace();
}
}
if(ps!=null){
try{
ps.close();
}
catch(Exception e){
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
private static Map<String,String> initUi(){
Scanner s = new Scanner(System.in);
System.out.print("用户名:");
String loginName = s.nextLine();
System.out.print("密码:");
String loginPwd = s.nextLine();
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}