Come eseguire l'escape delle stringhe in SQL Server utilizzando PHP?


89

Sto cercando l'alternativa di mysql_real_escape_string()per SQL Server. È la addslashes()mia opzione migliore o esiste un'altra funzione alternativa che può essere utilizzata?

mysql_error()Sarebbe utile anche un'alternativa a .


2
Per me non è una domanda duplicata perché riguarda il caso specifico MSSQL che non ha una DOP ufficiale correlata
Pierre de LESPINAY

Risposte:


74

addslashes()non è del tutto adeguato, ma il pacchetto mssql di PHP non fornisce alcuna alternativa decente. La soluzione brutta ma completamente generale è codificare i dati come una stringa esadecimale, ad es

$unpacked = unpack('H*hex', $data);
mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (0x' . $unpacked['hex'] . ')
');

Estratto, sarebbe:

function mssql_escape($data) {
    if(is_numeric($data))
        return $data;
    $unpacked = unpack('H*hex', $data);
    return '0x' . $unpacked['hex'];
}

mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (' . mssql_escape($somevalue) . ')
');

mysql_error()l'equivalente è mssql_get_last_message().


1
Oops, è SELECT SCOPE_IDENTITY ()!
Bryan Rehbein

4
@genio: Mmm, fantastico, tranne che in realtà lo è. Suppongo che non spiegheresti quello che consideri il problema?
caos

3
Hai provato questo con le colonne datetime? Ricevo questo errore: SQLSTATE[22007]: Invalid datetime format: 210 [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting datetime from binary/varbinary string.credo che questo metodo possa essere corretto solo se funziona con ogni tipo di dati MSSQL.
Alejandro García Iglesias

1
Il contenuto della mssql_escape()funzione restituita non lo fa per me. Il display di testo dopo aver effettuato una selezione sembra 0x4a2761696d65206269656e206c652063686f636f6c6174così illeggibile.
Jeff Noel

3
@ JeffNoel Probabilmente stai avvolgendo la stringa virgolette singole o doppie virgolette. Poiché l'elemento è sottoposto a escape in esadecimale, le virgolette non sono necessarie. SQL Server dovrebbe convertire il valore esadecimale in qualcosa che il db capisca.
danielson317

40
function ms_escape_string($data) {
        if ( !isset($data) or empty($data) ) return '';
        if ( is_numeric($data) ) return $data;

        $non_displayables = array(
            '/%0[0-8bcef]/',            // url encoded 00-08, 11, 12, 14, 15
            '/%1[0-9a-f]/',             // url encoded 16-31
            '/[\x00-\x08]/',            // 00-08
            '/\x0b/',                   // 11
            '/\x0c/',                   // 12
            '/[\x0e-\x1f]/'             // 14-31
        );
        foreach ( $non_displayables as $regex )
            $data = preg_replace( $regex, '', $data );
        $data = str_replace("'", "''", $data );
        return $data;
    }

Parte del codice qui è stato strappato da CodeIgniter. Funziona bene ed è una soluzione pulita.

EDIT: ci sono molti problemi con lo snippet di codice sopra. Per favore, non usarlo senza leggere i commenti per sapere cosa sono. Meglio ancora, per favore non usarlo affatto. Le query parametrizzate sono tuoi amici: http://php.net/manual/en/pdo.prepared-statements.php


1
Perché ne hai bisogno preg_replace? Non è str_replacesufficiente?
Gabe

gabe: Il preg_replace in questo caso era di permettermi di usare gli intervalli che mi venivano offerti nelle classi di caratteri delle espressioni regolari. Altrimenti ci sarebbero molte più sostituzioni di stringhe in questo.
genio

7
-1. Non è responsabilità di una funzione quoting manipolare i dati: tutto ciò che dovrebbe fare è assicurarsi che la stringa sia in un formato tale da poter essere aggiunta a un'istruzione SQL e sopravvivere senza modifiche.
cHao

6
Ci dispiace, ma questo è sbagliato dalla prima riga di codice - empty($value)restituirà truenon solo per '', ma anche per null, 0e '0'! Restituiresti una stringa vuota in tutti questi casi.
Nux

Ho votato al contrario, penso che sia una funzione perfettamente funzionante fintanto che sei pienamente consapevole dei problemi sopra. Lo chiamerei ms_escape_and_strip_string, quindi chiunque altro ci lavori vedrebbe che esegue entrambe queste attività. Avere una stringa vuota restituita in più casi va bene fintanto che lo si tiene conto, a meno che non mi manchi solo un punto più grande qui. Se questo non si adatta alle tue esigenze, puoi sempre togliere quella linea e sostituirla con una logica adatta alle tue esigenze.
NateDSaint

16

Perché dovresti preoccuparti di sfuggire a qualcosa quando puoi usare i parametri nella tua query ?!

sqlsrv_query(
    $connection, 
    'UPDATE some_table SET some_field = ? WHERE other_field = ?', 
    array($_REQUEST['some_field'], $_REQUEST['id'])
)

Funziona correttamente in seleziona, elimina, aggiorna indipendentemente dal fatto che i parametri dei valori siano nullo meno. È una questione di principio: non concatenare SQL e sarai sempre al sicuro e le tue query si leggeranno molto meglio.

http://php.net/manual/en/function.sqlsrv-query.php


Questo è l'approccio corretto. Utilizzare sempre i parametri anziché le query ad hoc. Tuttavia, l'OP non utilizza i driver sqlsrv. Sta usando i driver mssql. quindi il collegamento da usare per quelli di voi che sono bloccati usando i driver sqlsrv è http://php.net/manual/en/function.mssql-query.php .
smulholland2

1
@ smulholland2 Intendevi "o quelli di voi bloccati utilizzando i driver MSSQL "
Konstantin

Uno scenario potrebbe essere se si desidera generare un file di istruzioni INSERT da utilizzare in uno scenario di migrazione dei dati.
Gary Reckard

11

Potresti esaminare la libreria PDO . È possibile utilizzare istruzioni preparate con PDO, che eseguiranno automaticamente l'escape di eventuali caratteri errati nelle stringhe se si eseguono correttamente le istruzioni preparate. Questo è solo per PHP 5 credo.


Con alcuni dei comportamenti a metà che ho visto con PDO, avrei dovuto fare alcuni test seri prima di fidarmi di esso per sfuggire a tutti i dati correttamente.
caos

@ Caos Davvero? Non sono a conoscenza di questo .. hai un link ad un articolo?
alex

Quello a cui stavo pensando erano i guai che questo tizio qui stava avendo ieri con PDO. Roba di transazione non correlata, ma insignificante. Combinalo con tutta la cronologia di dati inadeguati che sfuggono in PHP (php.net dice alle persone di usare addlashes ()!) E divento molto sospettoso.
caos

2
Adoro PDO e l'ho provato prima, ma quello per MSSQL (su Unix, basato su dblib) a volte non riesce (errore di segmentazione), ecco perché ho fatto ricorso a mssql_escape definito sopra.
lapo

Grazie per il tuo commento, @Iapo. Stavo pensando di passare a PDO per un progetto mssql, in particolare per scappare, ma mi hai risparmiato il problema.
Winfield Trail


2

Per evitare virgolette singole e doppie, devi raddoppiarle:

$value = 'This is a quote, "I said, 'Hi'"';

$value = str_replace( "'", "''", $value ); 

$value = str_replace( '"', '""', $value );

$query = "INSERT INTO TableName ( TextFieldName ) VALUES ( '$value' ) ";

eccetera...

e attribuzione: carattere di fuga in Microsoft SQL Server 2000


2

Dopo aver lottato per ore con questo, ho trovato una soluzione che sembra quasi la migliore.

La risposta di Chaos di convertire i valori in hexstring non funziona con tutti i tipi di dati, in particolare con le colonne datetime.

Uso PHP PDO::quote(), ma poiché viene fornito con PHP, PDO::quote()non è supportato per MS SQL Server e restituisce FALSE. La soluzione per farlo funzionare era scaricare alcuni bundle Microsoft:

Dopodiché puoi connetterti in PHP con PDO utilizzando un DSN come il seguente esempio:

sqlsrv:Server=192.168.0.25; Database=My_Database;

L'utilizzo dei parametri UIDe PWDnel DSN non ha funzionato, quindi nome utente e password vengono passati come secondo e terzo parametro sul costruttore PDO durante la creazione della connessione. Ora puoi usare PHP PDO::quote(). Godere.



0

Attenzione: questa funzione è stata RIMOSSA in PHP 7.0.0.

http://php.net/manual/en/function.mssql-query.php

Per chiunque utilizzi ancora queste funzioni mssql_ *, tieni presente che sono state rimosse da PHP a partire dalla v7.0.0. Quindi, ciò significa che alla fine dovrai riscrivere il codice del modello per utilizzare la libreria PDO, sqlsrv_ * ecc. Se stai cercando qualcosa con un metodo "quoting / escaping", consiglierei PDO.

Le alternative a questa funzione includono: PDO :: query (), sqlsrv_query () e odbc_exec ()



0

Affinché la conversione ritorni i valori esadecimali in SQL in ASCII, ecco la soluzione che ho ottenuto su questo (usando la funzione da caos utente per codificare in esadecimale)

function hexEncode($data) {
    if(is_numeric($data))
        return $data;
    $unpacked = unpack('H*hex', $data);
    return '0x' . $unpacked['hex'];
}

function hexDecode($hex) {
    $str = '';
    for ($i=0; $i<strlen($hex); $i += 2)
        $str .= chr(hexdec(substr($hex, $i, 2)));
    return $str;
}

$stringHex = hexEncode('Test String');
var_dump($stringHex);
$stringAscii = hexDecode($stringHex);
var_dump($stringAscii);

0

È meglio evitare anche le parole riservate SQL. Per esempio:

function ms_escape_string($data) {
    if (!isset($data) or empty($data))
        return '';

    if (is_numeric($data))
        return $data;

    $non_displayables = array(
        '/%0[0-8bcef]/',        // URL encoded 00-08, 11, 12, 14, 15
        '/%1[0-9a-f]/',         // url encoded 16-31
        '/[\x00-\x08]/',        // 00-08
        '/\x0b/',               // 11
        '/\x0c/',               // 12
        '/[\x0e-\x1f]/',        // 14-31
        '/\27/'
    );
    foreach ($non_displayables as $regex)
        $data = preg_replace( $regex, '', $data);
    $reemplazar = array('"', "'", '=');
    $data = str_replace($reemplazar, "*", $data);
    return $data;
}

-1

L'ho usato come alternativa a mysql_real_escape_string():

function htmlsan($htmlsanitize){
    return $htmlsanitize = htmlspecialchars($htmlsanitize, ENT_QUOTES, 'UTF-8');
}
$data = "Whatever the value's is";
$data = stripslashes(htmlsan($data));

-2

Si potrebbe rotolare la propria versione di mysql_real_escape_string, (e migliorare su di essa), con la seguente espressione regolare: [\000\010\011\012\015\032\042\047\134\140]. Ciò si occupa dei seguenti caratteri: null, backspace, tabulazione orizzontale, nuova riga, ritorno a capo, sostituto, virgolette doppie, virgolette singole, barra rovesciata, accento grave. Backspace e tabulazione orizzontale non sono supportati da mysql_real_escape_string.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.