栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

解决JDBC实现用户登录时出现SQL注入问题详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决JDBC实现用户登录时出现SQL注入问题详解

JDBC实现用户登录时出现SQL注入问题
    • JDBC实现用户登录:
    • SQL注入
    • 解决SQL注入

JDBC实现用户登录:
public class jdbcTest06{
    public satic void main(String[] args){
		Map userLoginInfo initUI(); 
        boolean loginSuccess = login(userLoginInfo);
        System.out.println(loginSuccess ? "登录成功" : "登录失败");
    }
    private static boolean login(Map userLoginInfo){
        boolean loginSuccessornot = false;
        
        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");
        
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
            // 3. 获取数据库操作对象
            stmt = conn.creatStatement();
            // 4. 执行SQL语句
            String sql = "select * from t_user where loginName '"+loginName+"' and '"+loginPwd+"'";
            rs = stmt.executeQuery(sql);
            // 5. 处理结果集
            if(rs.next()){
                loginSuccessornot = true;
            }else{
                loginSuccessornot = false;
            }
        }catch(SQLException 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 loginSuccessornot;
    }
    private static Map iniUT(){
        Scanner s = new Scanner(System.in);
        System.out.println("用户名:");
        String loginName = s.nextLine();
        System.out.println("密码:");
        String loginPwd = s.nextLine();
        
        Map userLoginInfo = new HaspMap<>();
        userLoginInfo.put("loginName","loginName");
        userLoginInfo.put("loginPwd","loginPwd");
        return userLoginInfo;
    }
}

  


SQL注入

当前程序存在问题:

  输入:
    用户名:fdsa
    密码:fdsa’ or ‘1’ = ‘1
  输入:
    登录成功 ( 数据库中不存在这条数据 )

这种现象被成为SQL注入

问题代码块:

jade,mysql

        Statement stmt = null;

		// 3. 获取数据库操作对象
        stmt = conn.creatStatement();
        // 4. 执行SQL语句
        String sql = "select * from t_user where 
        	'"+loginName+"' and '"+loginPwd+"'";
        rs = stmt.executeQuery(sql);

以上代码块解析:

  获取数据库操作对象 stmt 后执行SQL语句将传了loginName 和 loginPwd 两个参数的SQL语句作为参数传给了 executeQuery() 方法
  然后 executeQuery() 方法进行编译,就会把 fdsa’ or ‘1’ = ‘1 作为sql语句一起编译了,

看看编译后的sql语句:

 sql: "select * from t_user where loginName = 'fdsa' and loginPwd = 'fdsa' or '1' = '1'"

  可以看到查询语句的where条件变成了
  loginName = 'fdsa' and loginPwd = 'fdsa' or '1' = '1'"

  意思就是 where(loginName = 'fdsa' and loginPwd = 'fdsa') 或者 ('1' = '1')

  而'1' = '1'恒成立,所以无论怎么查询都能查到结果,甚至是将所有的用户账号密码都查了出来,最后完成登录

所以出现SQL注入的关键是:
  用户输入的非法信息被数据库操作系统编译了,例如用户输入了含有SQL语句的关键字,并且这些关键字参与了SQL语句的编译过程
  


解决SQL注入

  只要用户提供的信息不参与SQL编译过程,即使提供的信息含有关键字等非法信息,但是只要不参加数据库操作系统的编译九不会形成注入

  要想用户信息不参与SQL语句的编译,那必须适合用java.sql.PreparedStatement

  PreparedStatement 接口集成了java.sql.Statement,PreparedStatement 是属于预编译的数据库操作对象

  PreparedStatement 的原理是预先对SQL语句的框架进行编译,然后再给SQL语句传值

解决SQL注入的关键是:
  用户提供的信息中即使含有sql语句的关键字,但是这些关键字并没有参与编译,不起作用

解决注入代码:

package com.hyqwsq.jdbc;

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


public class jdbcTest06 {
    public static void main(String[] args) {
        // 初始化一个界面,创建一个可以初始化界面的方法,
        // 接收的返回值是用户名和密码,放到一个MAP容器中
        Map userLoginInfo = initUI();

        // 验证用户和密码并登录,创建登录方法,传进用户信息,userLoginInfo为参数
        // 登录失败或者成功只有两种结果,所以方法返回一个布尔类型就好
        boolean loginSuccess = login(userLoginInfo);
        // 最后输出结果
        System.out.println(loginSuccess ? "登录成功" : "登录失败");
    }

    
    private static boolean login(Map userLoginInfo) {
        // 打标记
        boolean loginSuccessornot = false;

        // 单独定义变量
        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");

        //JDBC代码
        Connection conn = null;
        // Statement stmt = null;
        // 换成预编译的数据库操作对象 PrepareSratement
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hyqwsq","root","13903014064");
            // 3.获取编译的数据库操作对象
            // 将原来的值换成占位符 ?
            // 这样sql语句变成了框架,? 表示占位符,一个占位符将接收一个值,占位符不能使用单引号括起来
            String sql = "select * from t_user where loginName = ? and ?";
            // 程序执行到这里,会发送SQL语句框架给DBMS,然后DBMS进行SQL语句的预先编译
            ps = conn.prepareStatement(sql);
            // 给占位符 ? 传值(第一个占位符的下标是1, 第二个占位符的下标是2,JDBC中所有下标从1开始)
            ps.setString(1,loginName);
            ps.setString(2,loginPwd);
            // getString()方法传进去字符串后会自动加上单引号,如果是其getInt()就不会

            // 4.执行SQL
            //把用户数据的用户名的用户密码的字符串拼到字符串中:双引号中间加两个加号
            //String sql = "select * from t_user where loginName = '"+userLoginInfo.get("loginName")+"' and loginPwd = '"+userLoginInfo.get("loginPwd")+"'";

            //单独定义变量后
            // String sql = "select * from t_user where loginName = '"+loginName+"' and '"+loginPwd+"'";
            // 以上正好完成了SQL语句的拼接,以下代码的含义是:发送SQL语句给DBMS,DBMS进行编译
            // 正好将用户提供的非法信息编译减去,导致了原来的SQL语句含义被扭曲了
            rs = ps.executeQuery(sql);

            // 5.处理结果集
//            while(rs.next()){}
            //不需要循环查看结果集,因为返回值为布尔类型,只需要看有没有结果集就好
            if(rs.next()){
                //登录成功
                loginSuccessornot = true;
            }


        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            // 6.关闭通道,释放资源
            if(rs != null){
                try {rs.close();} catch (SQLException throwables) {throwables.printStackTrace();}}
            if(ps != null){
                try {ps.close();} catch (SQLException throwables) {throwables.printStackTrace();}}
            if(conn != null){
                try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}
        }

        return loginSuccessornot;
    }

    
    private static Map initUI() {
        Scanner s = new Scanner(System.in);
        //输入用户名
        System.out.println("用户名:");
        String loginName = s.nextLine();
        // 输入密码
        System.out.println("密码:");
        String loginPwd = s.nextLine();

        //将数据组装到嘛Map中
        Map userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName","loginName");
        userLoginInfo.put("loginPwd","loginPwd");
        return userLoginInfo;
    }


}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/600901.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号