Explicación detallada de la etiqueta bind de MyBatis, bind previene casos de inyección SQL y explicación detallada

1. etiqueta de enlace

  • La etiqueta de vinculación puede usar una expresión OGNL para crear una variable y vincularla al contexto.

gramática:

<bind name = "variable a vincular" value = "valor final de vinculación" />

  • nombre: una variable de contexto, como la variable #{userName} en SQL, donde el nombre se completa con el nombre de usuario
  • valor: el valor final de la variable de vinculación, como nombre="nombre de usuario", luego el valor es el valor real final de #{nombre de usuario}, que puede procesar los parámetros pasados, como: valor = " '%' + nombre de usuario + '%' ", para unir los símbolos % antes y después del nombre de usuario entrante.

2. Función

1>Compatible con las diferencias de sintaxis SQL entre diferentes bases de datos, amigable con la migración de bases de datos

Debido a las diferencias en algunas escrituras de SQL en diferentes bases de datos, el uso de bind puede adaptarse a las diferencias entre diferentes bases de datos.

Por ejemplo: en una consulta difusa, use la función de empalme de cadenas concat para admitir múltiples parámetros en MySQL, pero solo se pueden escribir dos parámetros en Oracle, de la siguiente manera:

Método de escritura MySQL:

select id,serial from payment 
where
serial like concat("%",#{serial},"%")

Método de escritura de Oracle:

select id,serial from payment
where
serial like concat("%",concat(#{serial},"%"))

Por lo tanto, cuando Oracle se migre a MySQL, hará que mybatis informe un error.Podemos usar la etiqueta de vinculación para ser directamente compatible, de la siguiente manera:

select id,name from payment
where
<bind name="name" value="'%'+name+'%'" />
name  like #{name}  --name实际是bind标签中的value

2> Prevenir la inyección de SQL

Tome la consulta difusa como ejemplo, cuando usamos directamente la concatenación de cadenas SQL sin usar la función concat, de la siguiente manera:

select id,serial from payment
where
serial like "%${serial}%"
--注意:Oracle写法为:"%"||${serial}||"%"

Nota: Esto solo puede ser: "%${serial}%", no "%#{serial}%"

  • "%${serial}%": ${serial} se considerará como un marcador de posición de cadena, y esta parte se reemplazará directamente cuando se ejecute SQL
  • "%#{serial}%": #{serial} no tendrá efecto cuando la cadena se concatena, es directamente una cadena "%#{serial}%"

Probamos la declaración de consulta difusa de SQL anterior, caso de inyección de SQL:

<1>MySQL tiene datos de la tabla de pagos

<2> XML de asignación de mybatis
<select id="getBySerial" resultMap="payMap">
    select id,serial from payment where
    serial like "%${serial}%"
</select>
<3>interfaz del controlador

Los códigos de capa de servicio y dao se omiten directamente sin ningún procesamiento, y el SQL en el xml se llamará directamente

@RequestMapping("/payment/getBySerial")
public R<List<PaymentDTO>> getBySerial(PaymentDTO dto){
	return R.ok(paymentService.getBySerial(dto));
}
<4> prueba

Prueba de solicitud normal: http://127.0.0.1:6061/payment/getBySerial?serial=O

La instrucción SQL ejecutada en este momento es:

select id,serial from payment where
serial like "%O%"

Pruebe la solicitud de inyección SQL: http://127.0.0.1:6061/payment/getBySerial?serial=O" o 1=1 o "serial=O

La instrucción SQL ejecutada en este momento es:

select id,serial from payment where 
serial like "%O" or 1=1 or "serial=O%"

! ! ! o 1 = 1: ¡La condición del filtro es directamente inválida y se pueden obtener todos los datos de la tabla! ,como sigue:

<5> enlace para evitar la modificación de inyección de SQL

Por lo tanto, no podemos usar #{} para evitar la inyección SQL en el método de escritura mencionado anteriormente. En el caso de no usar funciones SQL y códigos Java sin empalmar %, queremos evitar la inyección SQL. Podemos usar la etiqueta de enlace + #{ } para reemplazar $ { } forma de empalme , el caso es el siguiente:

  • Cambie el SQL en xml y otros códigos no se mueven:
select id,serial from payment where
<bind name="serial" value="'%'+serial+'%'" />
serial like #{serial}

Continuar probando:

Prueba de solicitud normal: http://127.0.0.1:6061/payment/getBySerial?serial=O

La instrucción SQL ejecutada en este momento es:

Resultado de la solicitud:

Pruebe la solicitud de inyección SQL: http://127.0.0.1:6061/payment/getBySerial?serial=O" o 1=1 o "serial=O

La instrucción SQL ejecutada en este momento es:

El resultado es el siguiente:

Supongo que te gusta

Origin blog.csdn.net/weixin_42675423/article/details/132150420
Recomendado
Clasificación