
本程序是模拟用户登录 并且解决SQL注入问题 sql注入的根本原因是:先进行字符串的拼接,再进行编译 程序说明:本程序的输入采取了scanner.nextline()方法 即意味着可以接收一行的密码 而密码是sql语言的一部分,因此可以创建 or 关键字破坏sql的where条件 例如:
此时人为地破坏了sql正常的语句。
原本的代码:
//3.获取数据库 *** 作对象
stmt = conn.createStatement();
//4.执行sql语句
// mysql语句有单引号如何写入String
// 1.首先按照sql语句写下你要查询的语句,变量的地方先空着
// 2.然后在单引号里加双引号和两个加号 如 '"++"' 此时再向两个加号之间加上变量。
// String sql = "select * from t_user where login_name ='' and login_pwd=''";
String sql = "select * from t_user where login_name ='"+loginname+"' and login_pwd='"+loginpwd+"'";
// 3.但是这种情况会出现sql的注入问题(即输入的密码为 123 or '1'= 1 )
rs = stmt.executeQuery(sql);//rs返回的是光标
解决方法为:改变原本的Statement *** 作对象,使用预编译的 *** 作对象PreparedStatement
package JDBC;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Scanner;
public class JDBClogin_user {
public static void main(String[] args) {
// 自动创建函数:只需要在未创建的函数名处使用alt+enter 即可为其创建函数
//初始化界面
Map userlogin_info = initUI();
//链接数据库,验证用户名和密码是否正确
boolean ok = check_nameandpwd(userlogin_info.get("loginname"),userlogin_info.get("loginpwd"));
System.out.println(ok ? "登录成功" : "登录失败");// ?为正,登录成功,否则登录失败
}
private static boolean check_nameandpwd(String loginname, String loginpwd) {
//数据库的六部 哐哐哐打出来或者找之前写好的模板直接复制 这里采取第二种注册驱动的方法
Connection conn = null;
// Statement stmt = null;
PreparedStatement stmt = null;
ResultSet rs = null;
//资源绑定器
ResourceBundle bundle = ResourceBundle.getBundle("resourses/db");
String driver= bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");
//下面的模板就是 try{...}catch{...}finally{...}
try{
//1.注册驱动的第二种方式:类加载注册
// Class.forName("com.mysql.jdbc.Driver");//可以写到配置文件当中
Class.forName(driver);
//2.获取连接
// conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/trade_for_book","root","002415");
conn = DriverManager.getConnection(url,user,password);
//3.获取数据库 *** 作对象
// stmt = conn.createStatement();
String sql = "select * from t_user where login_name = ? and login_pwd= ?";//一个问号是一个占位符,只能接受一个值
stmt = conn.prepareStatement(sql);
//给问号传值 那么无论你输入的有什么关键字,最终只是一个值,不会改变sql语句的条件
stmt.setString(1,loginname);
stmt.setString(2,loginpwd);
//4.执行sql语句
// mysql语句有单引号如何写入String
// 1.首先按照sql语句写下你要查询的语句,变量的地方先空着
// 2.然后在单引号里加双引号和两个加号 如 '"++"' 此时再向两个加号之间加上变量。
// String sql = "select * from t_user where login_name ='' and login_pwd=''";
// String sql = "select * from t_user where login_name ='"+loginname+"' and login_pwd='"+loginpwd+"'";
// 3.但是这种情况会出现sql的注入问题(即输入的密码为 123 or '1'= 1 )
// rs = stmt.executeQuery(sql);//rs返回的是光标
rs = stmt.executeQuery();//预编译就不需要传sql语句了
// System.out.println(sql);
if (rs.next()){
return true;
}else {
return false;
}
}catch(Exception e){
e.printStackTrace();
}finally {
if (rs != null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if (stmt != null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
return false;
}
private static Map initUI(){
System.out.println("欢迎使用该系统,请输入你的用户名和密码");
//读取String用next(),以空格划分
Scanner s = new Scanner(System.in);
System.out.print("用户名:");
// String loginname = s.next();
String loginname = s.nextLine();
System.out.print("密码:");
// String loginpwd = s.next();
String loginpwd = s.nextLine();
//将用户名和密码放到Map集合中
Map userlogin__info = new HashMap<>();
userlogin__info.put("loginname",loginname);
userlogin__info.put("loginpwd",loginpwd);
//返回Map
return userlogin__info;
}
}
// 数据库内容
// drop table if exists t_user;
// create table t_user(
// id int primary key auto_increment, auto_increment表示自增
// login_name varchar(255) unique ,
// login_pwd varchar(255),
// real_name varchar(255)
// );
// insert into t_user(login_name,login_pwd,real_name) values('admin','123','孙子昂');
// insert into t_user(login_name,login_pwd,real_name) values('admin01','123','xx02');
//
// select *form t_user;
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)