[JavaWeb] ¿Qué es la inyección sql?

1. ¿En qué se inyecta sql?

Muchos de los programas que utilizamos tienen un nombre de usuario y una contraseña, y una gran cantidad de datos de usuario se almacenan en el servidor del software.
Cuando el usuario inicia sesión, el nombre de usuario y la contraseña deben ser correctos para iniciar sesión correctamente.
Bien, ahora simulemos este escenario.
Cree una tabla de información de usuario con declaraciones sql y luego agregue datos.
inserte la descripción de la imagen aquí
Ahora, para simular el caso del inicio de sesión del usuario, la lógica comercial es la siguiente:

  • Los nombres de usuario son únicos.
  • El inicio de sesión del usuario debe garantizar que tanto el nombre de usuario como la contraseña sean correctos.
  • Consulta la cantidad de datos en la base de datos que satisfacen el nombre de usuario y la contraseña al mismo tiempo.
  • Si el número es 1, el inicio de sesión es exitoso y se notifica al usuario.
  • De lo contrario, el inicio de sesión falla y se solicita al usuario que verifique el nombre de usuario y la contraseña.

inserte la descripción de la imagen aquí
Agregar un conocimiento: conocimiento de ResultSet

Cuando ejecutamos ciertas consultas SQL (generalmente consultas SELECT), devuelven datos tabulares.
La interfaz java.sql.ResultSet representa dichos datos tabulares devueltos por sentencias SQL.
Es decir, el objeto ResultSet guarda los datos del formulario devueltos por el método que ejecuta la instrucción que requiere la base de datos (generalmente el método executeQuery() de la interfaz de instrucción).
El objeto ResultSet tiene un cursor/puntero a la fila actual. Inicialmente, este cursor se coloca antes de la primera línea.
inserte la descripción de la imagen aquí
Cuando se ejecuta el método next() de la interfaz ResultSet, el puntero del objeto actual (ResultSet) se mueve desde la posición actual a la fila siguiente.
Es decir, la primera vez que se llama al método next(), el puntero/cursor del conjunto de resultados se moverá a la primera fila (desde la posición predeterminada).
Y cuando se llama al método next() por segunda vez, el cursor del conjunto de resultados se moverá a la segunda fila.
Este método devuelve un valor booleano que especifica si el objeto ResultSet contiene más filas. Este método devuelve falso si no hay una fila al lado de la posición actual y verdadero en caso contrario.

① Obtener la conexión y crear el objeto de instrucción de ejecución
Utilice la clase de herramienta jdbc para obtener directamente la conexión y crear el objeto de instrucción de ejecución al mismo tiempo.

②Escribir sentencia sql y ejecutar
sentencia sql se escribe en forma de cadena en Java, por lo que se debe convertir su significado.
Al mismo tiempo, debido a que name y pwd son dos variables, deben empalmarse.

inserte la descripción de la imagen aquí
Al escribir declaraciones SQL en Java, primero puede escribirlas en la base de datos y ejecutarlas para ver si hay algún problema.
Si no hay problema, empalme en la cadena de Java correspondiente.

③Resultados del procesamiento
Estamos consultando la cantidad de datos que cumplen las condiciones, es decir, count( ), y la cantidad de datos que cumplen las condiciones se puede obtener llamando al método getInt(count()).De acuerdo con la lógica comercial: si es 1, el inicio de sesión es exitoso; de lo contrario, el inicio de sesión falla.

2. Pruebas e inyección SQL

Hagamos una prueba.
inserte la descripción de la imagen aquí

①La tabla de nombre de usuario y contraseña existe,
por lo que el inicio de sesión es exitoso.

②La contraseña 1234 es incorrecta,
por lo que falló el inicio de sesión Entonces, ahora viene el problema, consulte ③La contraseña 1234 es incorrecta, ¿por qué el inicio de sesión fue exitoso?
Lo complicado aparece en el nombre de usuario, este nombre de usuario es String nusename="liuxiaoai'- -", - -aquí están los dos caracteres de línea horizontal conectados)
Coloque el nombre de usuario y la contraseña en la cadena de Java y luego conviértalos en una instrucción SQL.
inserte la descripción de la imagen aquí

–" es un comentario en sql, y la siguiente declaración está comentada.
Significa que siempre que el nombre de usuario en el frente sea correcto, no importa cuál sea la contraseña en la parte posterior, y no importa si no lo escribe.
La comprensión simple es:
cuando el usuario envía datos. Algunos caracteres especiales se agregan artificialmente para cambiar la estructura de la declaración sql.
Finalmente, puede iniciar sesión sin un nombre de usuario o contraseña, y también puede completar ataques maliciosos.¿Cómo
prevenirlo?Utilice la precompilación.

3. Precompilar

La precompilación, como sugiere el nombre, es precompilación, el código es el siguiente:
inserte la descripción de la imagen aquí
①Marcador de posición
? Es un marcador de posición que indica que la ubicación es un parámetro.
Tiene un efecto muy poderoso en el sentido de que los parámetros en el marcador de posición deben ser cadenas ordinarias.
¿Qué significa eso? Aprendimos sobre los personajes de escape antes. Originalmente, "- -" significa un comentario en sql, pero se escapa a un carácter ordinario a través de un marcador de posición y no tiene la función de un comentario.

②Precompilación
La precompilación es equivalente a avanzar en la instrucción sql, compilar primero y luego configurar los parámetros.Anteriormente, la instrucción sql se ejecutaba cuando se llamaba al método executeQuery(), y PreparedStatement es una subinterfaz de la instrucción. Preparado significa preparación y avance.

③El método setString() del índice de parámetros
es para asignar un valor específico al marcador de posición, y el parámetro representa el índice del marcador de posición "?" en la instrucción SQL: 1 representa el
primer signo de interrogación es el nombre;
2 representa el segundo El signo de interrogación significa pwd.
donde el índice comienza a contar desde 1 desde la izquierda.
Lo anterior es la descripción de la precompilación de inyección sql y sus medidas preventivas. La precompilación puede prevenir la inyección sql, y la eficiencia es alta, lo cual es muy práctico.

Resumir

¿Pasar la declaración sql a PreparedStatement para la compilación por adelantado y usar los parámetros que se pasarán más tarde? En su lugar, la instrucción sql se precompilará y, después de la compilación, será una instrucción sql que deberá pasar parámetros (por ejemplo: seleccionar * del usuario donde id=? ), y luego pasar los parámetros obtenidos por la recepción a la instrucción sql compilada a través del conjunto De esta manera, se evita el problema de inyección de sql causado por la manipulación de caracteres especiales en sql durante la etapa de compilación, y el uso de PreparedStatement ayuda a mejorar el rendimiento de la ejecución de la base de datos hasta cierto punto.

Supongo que te gusta

Origin blog.csdn.net/wang_qiu_hao/article/details/125202559
Recomendado
Clasificación