Come eseguire il escape di stringhe in SQL Server utilizzando PHP?


85

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

Modifica: alternativa per mysql_error() sarebbe anche utile.

+2

Per me non è una questione duplicato perché riguarda il caso specifico MSSQL che non dispone di un correlato DOP ufficiale 04 mar. 132013-03-04 16:26:42

69

addslashes() non è completamente adeguato, ma il pacchetto mssql di PHP non fornisce alcuna alternativa decente. La soluzione brutto ma completamente generale è la codifica i dati come bytestring esagono, cioè

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

astratto, 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() equivalente è mssql_get_last_message().

  0

Conosci l'equivalente per mysql_insert_id() per caso? 22 feb. 092009-02-22 12:20:40

  0

Sì, fai un SELECT @@ IDENTITY. 22 feb. 092009-02-22 12:24:31

  0

Caos, puoi dare un esempio di una funzione di 'escape' che prenderebbe una stringa come argomento e restituire l'alternativa esadecimale come risultato usando il metodo che hai dato? Accetterò la tua risposta quindi 22 feb. 092009-02-22 12:26:45

  0

Al momento non sono sicuro del requisito di doppia/quota per i valori esadecimali e di come i valori numerici saranno gestiti da questo metodo. Un esempio di utilizzo della funzione per evitare un valore e metterlo in una query sarà l'ideale. Grazie in anticipo 22 feb. 092009-02-22 12:27:45

  0

Speriamo più chiaro ora ... 22 feb. 092009-02-22 12:31:12

  0

1 domanda, il valore non deve essere racchiuso tra virgolette? Inoltre ... hai fatto dei test su come funziona con tutti i tipi di codifica dei caratteri, ecc.? 22 feb. 092009-02-22 12:33:22

  0

No. È un letterale stringa esadecimale; se lo inserisci tra virgolette, inserirai la stringa "0xf00ba44" o qualsiasi altra cosa nel tuo database invece dei dati originali. Non l'ho provato con diverse codifiche e suggerisco a chiunque usi questo codice di farlo prima di fare qualcosa di importante con esso. 22 feb. 092009-02-22 12:37:01

  0

Dovresti usare SELECT IDENTITY_SCOPE(); dalla tua stessa connessione per recuperare il tuo campo ID invece di @@ IDENTITY: è più affidabile. 02 mar. 092009-03-02 19:47:02

+1

Oops, il suo SELECT SCOPE_IDENTITY()! 02 mar. 092009-03-02 19:47:37

  0

La funzione non è giusta per quello che stava chiedendo. 26 mar. 102010-03-26 21:00:40

+4

@genio: Mmm, ottimo, tranne che in realtà lo è. Non credo che spiegheresti quello che consideri il problema? 28 mar. 102010-03-28 01:50:57

  0

@chaos Sono in ritardo per la festa, ma penso che Genio abbia avuto l'impressione che volesse spogliare personaggi pericolosi, quindi la sua soluzione. Penso che il tuo si adatti a ciò che mysql_real_escape_string fa meglio (almeno a quanto ho capito) 10 nov. 112011-11-10 14:58:12

  0

@chaos Dovrebbe funzionare con tutte le versioni di SQL Server? Sto usando SQL Server 2005 (Microsoft SQL Server Management Studio Express 9.00.2047.00) e non sembra funzionare. 31 gen. 122012-01-31 11:34:53

  0

@Nalum: Non lo so per certo, ma la sintassi letterale hexstring è l'unica cosa anche leggermente interessante che questa soluzione sta usando, e che deriva dallo standard SQL, quindi penserei che l'avrebbero implementata abbastanza presto. Prova a fare come 'SELECT 0x6869' o qualcosa del genere per vedere se il concetto bsaic funziona, suppongo. 01 feb. 122012-02-01 03:35:16

  0

@chaos Grazie per la risposta, non funziona, ho appena ottenuto il letterale hexstring indietro. Lo terrò a mente comunque. 01 feb. 122012-02-01 11:54:58

  0

@Nalum: L'unico modo che ha senso è se stai mettendo le virgolette intorno ad esso. È questo il caso? 01 feb. 122012-02-01 14:20:06

  0

@chaos No, ho copiato e incollato 'SELECT 0x6869' nel codice e anche in SQL Server Management Studio Express e ho ottenuto lo stesso risultato in entrambi. Quindi, a meno che non ci sia qualche impostazione in SQL Server che non lo consente, non so perché non funzioni come descrivi. 01 feb. 122012-02-01 16:42:33

  0

@Nalum: Si scopre che è solo la GUI che si sta facendo da padrona. In realtà sta preservando il formato delle specifiche originali attraverso la query. Crea una tabella Foo con una colonna nvarchar al suo interno e "INSERISCI IN VALORI Foo (0x6869)", quindi "SELEZIONA * DA Foo" e vedrai risultati diversi. 01 feb. 122012-02-01 18:37:31

  0

@chaos Grazie per tutto il vostro aiuto su questo. Quando lo faccio, ottengo un carattere di casella che suppongo abbia a che fare con la codifica dei caratteri. Non ho alcun controllo sul database, quindi non pensare che ci sia qualcosa che posso fare al riguardo.Ancora grazie per il tuo aiuto :) 03 feb. 122012-02-03 12:49:07

+2

Hai provato questo con colonne datetime? Viene visualizzato questo errore: 'SQLSTATE [22007]: Formato datetime non valido: 210 [Microsoft] [Driver ODBC SQL Server] [SQL Server] Conversione non riuscita durante la conversione di datetime da stringa binary/varbinary. Credo che questo metodo possa essere corretto solo se funziona con tutti i tipi di dati MSSQL. 19 giu. 122012-06-19 17:38:41

+1

Il contenuto della funzione 'mssql_escape()' restituita non lo fa per me. Il testo visualizzato dopo aver effettuato una selezione è simile a questo '0x4a2761696d65206269656e206c652063686f636f6c6174' quindi illeggibile. 14 ago. 122012-08-14 18:09:47

  0

non funziona per i tipi di formato data, datetime o testo. Qualche idea su come aggiungere quegli oggetti a questa funzione? Ho un lavoro che viene pubblicato per data e data ma non ho idea di come fare il testo. 18 set. 142014-09-18 16:42:09

+3

@JeffNoel Probabilmente avvolgendo le virgolette singole o doppie virgolette. Poiché l'oggetto è scappato in esagono, le virgolette non sono necessarie. SQL Server dovrebbe convertire il valore esadecimale in qualcosa che il db comprende. 18 set. 142014-09-18 16:44:19

  0

Penso che l'esempio migliore sia 'SELECT cast (0x6869 as varchar (2)) come SayHI' 21 apr. 162016-04-21 03:02:19

  0

Questo può metterti nei guai e non funziona su tutti i tipi di dati. Prendi in considerazione l'utilizzo di query parametrizzate. Se stai cercando di prevenire l'SQL injection, @ Konstantin ha una risposta più sicura qui sotto. 28 feb. 172017-02-28 22:21:56


10

È possibile esaminare PDO Library. È possibile utilizzare le istruzioni preparate con PDO, che sfuggiranno automaticamente a eventuali caratteri errati nelle stringhe se si eseguono correttamente le istruzioni preparate. Questo è solo per PHP 5, penso.

  0

Con alcuni dei comportamenti halfassed che ho visto fuori DOP, mi piacerebbe devo fare dei seri test prima che mi fossi fidato di sfuggire a tutti i dati correttamente. 22 feb. 092009-02-22 12:11:36

  0

@Chaos Davvero? Non ne sono a conoscenza .. hai un link ad un articolo? 22 feb. 092009-02-22 12:14:57

  0

Quello che stavo pensando era il problema che questo ragazzo qui stava avendo ieri con DOP. Transazioni non correlate, ma non impressionanti. Combinalo con tutta la storia di dati inadeguati che scappano in PHP (php.net dice alle persone di usare addslashes()!) E mi insospettisco molto. 22 feb. 092009-02-22 12:22:34

  0

Hmmm .. beh speriamo che abbiano corretto la parte di fuga. 22 feb. 092009-02-22 12:33:26

+2

Adoro i PDO e l'ho provato per primo, ma quello per MSSQL (su Unix, basato su dblib) a volte non riesce su di me (errore di segmentazione), ecco perché ho fatto ricorso a mssql_escape sopra definito. 06 set. 112011-09-06 20:58:44

  0

Grazie per il tuo commento, @Iapo. Stavo pensando di passare a PDO per un progetto mssql - in particolare per fuggire - ma mi hai salvato il problema. 24 lug. 132013-07-24 02:34:31


-2

È possibile eseguire il rollover della propria versione di mysql_real_escape_string (e migliorarla) con la seguente espressione regolare: [\000\010\011\012\015\032\042\047\134\140]. Questo si prende cura dei seguenti caratteri: null, backspace, tab orizzontale, nuova riga, ritorno a capo, sostituto, virgolette doppie, virgolette singole, backslash, accento grave. Backspace e scheda orizzontale non sono supportati da mysql_real_escape_string.

  0

-1 Il rollover è raramente la risposta giusta. 17 giu. 122012-06-17 07:15:18


38
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 è stata strappata da CodeIgniter. Funziona bene ed è una soluzione pulita.

+1

Confermato di funzionare !! Grazie uomo! 26 mar. 102010-03-26 21:03:03

+1

Perché hai bisogno di "preg_replace'? Il 'str_replace' è sufficiente? 26 mar. 102010-03-26 21:05:37

  0

gabe: Il preg_replace in questo caso è stato quello di permettermi di usare le gamme che mi sono state offerte nelle classi di caratteri delle espressioni regolari. Ci sarebbero molte più sostituzioni di corde in questo altrimenti. 26 mar. 102010-03-26 21:07:16

+6

-1. Non è responsabilità di una funzione di quotatura manipolare i dati: tutto ciò che deve fare è assicurarsi che la stringa sia in un formato tale che possa essere aggiunta a un'istruzione SQL e sopravvivere non modificata. 15 lug. 102010-07-15 06:38:48

+6

Siamo spiacenti, ma questo è sbagliato dalla prima riga di codice - 'empty ($ value)' restituirà 'true' non solo per' '' ', ma anche per' null', '0' e' '0'' ! Dovresti restituire una stringa vuota in tutti questi casi. 25 dic. 102010-12-25 13:45:40

  0

L'ho upvoted, penso che sia una funzione perfetta fino a quando si è pienamente consapevoli dei problemi di cui sopra. Lo chiamerei ms_escape_and_strip_string, quindi chiunque altro ci lavorasse avrebbe visto entrambe le cose. Avere una stringa vuota restituita in più casi va bene fintanto che si conta su di esso, a meno che non manchi solo un punto più grande qui. Se questo non si adatta alle tue esigenze, puoi sempre prendere quella linea e sostituirla con una logica adatta alle tue esigenze. 10 nov. 112011-11-10 14:40:14

  0

Questo non copre tutti i codici url come lo spazio =% 20. 30 mar. 162016-03-30 11:32:39


1

lo so, un po 'in ritardo, ma la risposta dal' 22 febbraio '09 alle 12:10 'dal caos non è adatta a tutte le domande. Ad esempio: "CREATE LOGIN [0x6f6c6f6c6f] DA WINDOWS" fornirà un'eccezione

p.s. guarda il driver mssql per php, http://msdn.microsoft.com/library/cc296181%28v=sql.90%29.aspx e la funzione sqlsrv_prepare, che può associare i parametri.

p.s.s. che non ti ha aiutato anche con la query sopra)


2

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

La risposta del caos di conversione dei valori in stringa esadecimale non funziona con tutti i tipi di dati, in particolare con le colonne datetime.

Uso il codice 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 è stato quello di scaricare alcuni bundle Microsoft:

Dopo di che è possibile collegare in PHP con DOP utilizzando un DSN come il seguente esempio:

sqlsrv:Server=192.168.0.25; Database=My_Database; 

Utilizzando i parametri UID e PWD nel DSN non ha funzionato, così username e password sono passati come secondo e terzo parametro sul costruttore PDO durante la creazione della connessione. Ora è possibile utilizzare PHP PDO::quote(). Godere.


2

Per sfuggire virgolette doppie single o, bisogna raddoppiare in su:

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

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

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

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

ecc ...

e di attribuzione: Escape Character In Microsoft SQL Server 2000


5

un altro modo per gestire le virgolette singole e doppie è

function mssql_escape($str) 
{ 
    if(get_magic_quotes_gpc()) 
    { 
    $str= stripslashes($str); 
    } 
    return str_replace("'", "''", $str); 
} 
  0

ottima risposta e grazie 19 gen. 162016-01-19 12:46:33

  0

get_magic_quites_gpc è stato DEPRECATO dal PHP 5.3.0 e RIMOSSO a partire da PHP 5.4.0. Vedi http://php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc 19 gen. 182018-01-19 14:09:15


9

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

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

Funziona proprio nel seleziona, cancella, aggiorna indipendentemente dal fatto che i parametri di valori sono null o meno. Prendi una questione di principio - Non concatenare SQL e sei sempre al sicuro e le tue letture sono molto migliori.

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

  0

Questo è l'approccio corretto. È necessario utilizzare sempre i parametri anziché le query ad hoc. Tuttavia, l'OP non sta utilizzando i driver sqlsrv. Sta usando i driver mssql. quindi il link da utilizzare per quelli di voi bloccati con i driver sqlsrv è [http://php.net/manual/en/function.mssql-query.php](http://php.net/manual/en/function. mssql-query.php). 28 feb. 172017-02-28 22:19:43

+1

@ smulholland2 Intendevi "o quelli di te bloccati usando _MSSQL_ drivers" 01 mar. 172017-03-01 09:51:38


0

Warning: This function was REMOVED in PHP 7.0.0.

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

Per chiunque ancora utilizzando queste mssql_ * funzioni, tenere presente che essi sono stati rimossi da PHP come di v7.0.0. Quindi, questo significa che alla fine dovranno riscrivere il codice modello di usare sia alla biblioteca DOP, sqlsrv_ * ecc Se siete alla ricerca di qualcosa con un metodo "citando/fuga", mi sento di raccomandare DOP.

Alternatives to this function include: PDO::query(), sqlsrv_query() and odbc_exec()


-1

Per la conversione per ottenere il HEX in SQL di nuovo in ASCII Ecco la soluzione ho ottenuto su questo (utilizzando la funzione dal Caos per codificare in Hex)

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

Se si utilizza DOP , puoi utilizzare il metodo PDO::quote.


-1

Ho utilizzato questo come alternativa di 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)); 

0

Non è meglio per sfuggire 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; 
}