Domanda

Conosco alcune delle nozioni di base, ma ciò di cui vorrei sapere di più è quando e perché la gestione degli errori (comprese le eccezioni di lancio) dovrebbe essere usata in PHP, specialmente su un sito live o un'app web. È qualcosa che può essere abusato e, in tal caso, che aspetto ha l'abuso? Ci sono casi in cui non dovrebbe essere usato? Inoltre, quali sono alcuni dei problemi di sicurezza comuni relativi alla gestione degli errori?

È stato utile?

Soluzione

Una cosa da aggiungere a ciò che è stato già detto è che è fondamentale registrare gli errori nell'applicazione Web in un registro. In questo modo, come Jeff "Coding Horror" Atwood suggerisce, saprai quando i tuoi utenti avranno problemi con la tua app (invece di "chiedere loro cosa non va").

Per fare ciò, raccomando il seguente tipo di infrastruttura:

  • Crea un " crash " tabella nel database e un set di classi wrapper per la segnalazione di errori. Consiglio di impostare le categorie per gli arresti anomali ("blocco", "sicurezza", "errore PHP / avviso" (vs eccezione), ecc.).
  • In tutto il codice di gestione degli errori, assicurati di registrare l'errore. Fare questo in modo coerente dipende da quanto bene hai creato l'API (sopra passaggio): dovrebbe essere banale registrare gli arresti anomali se fatto correttamente.

Credito extra: a volte, i tuoi arresti anomali saranno arresti anomali a livello di database: ad es. server DB inattivo, ecc. In tal caso, la tua infrastruttura di registrazione degli errori (sopra) fallirà (non puoi registrare l'incidente nel DB perché il registro tenta di scrivere nel DB). In tal caso, scriverei la logica di failover nella classe del wrapper Crash in

  • invia un'email all'amministratore, E / O
  • registra i dettagli dell'arresto in un file di testo semplice

Tutto ciò suona eccessivamente, ma credetemi, questo fa la differenza nel fatto che la vostra richiesta sia accettata come "stabile". o "traballante". Questa differenza deriva dal fatto che tutte le app iniziano come traballanti / si bloccano continuamente, ma quegli sviluppatori che conoscono tutti i problemi con la loro app hanno la possibilità di risolverlo effettivamente.

Altri suggerimenti

In parole povere, gli errori sono un retaggio in PHP, mentre le eccezioni sono il modo moderno di trattare gli errori. La cosa più semplice, quindi, è impostare un gestore degli errori, che genera un'eccezione. In questo modo tutti gli errori vengono convertiti in eccezioni, quindi puoi semplicemente gestire uno schema di gestione degli errori. Il seguente codice convertirà gli errori in eccezioni per te:

function exceptions_error_handler($severity, $message, $filename, $lineno) {
  if (error_reporting() == 0) {
    return;
  }
  if (error_reporting() & $severity) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
  }
}
set_error_handler('exceptions_error_handler');
error_reporting(E_ALL ^ E_STRICT);

Ci sono alcuni casi, in cui il codice è progettato specificamente per funzionare con errori. Ad esempio, il metodo schemaValidate di DomDocument genera avvisi durante la convalida di un documento. Se converti gli errori in eccezioni, smetterà di convalidare dopo il primo errore. Alcune volte questo è quello che vuoi, ma quando convalidi un documento, potresti effettivamente voler tutti errori. In questo caso, è possibile installare temporaneamente un gestore degli errori, che raccoglie gli errori. Ecco un piccolo frammento, che ho usato a tale scopo:

class errorhandler_LoggingCaller {
  protected $errors = array();
  function call($callback, $arguments = array()) {
    set_error_handler(array($this, "onError"));
    $orig_error_reporting = error_reporting(E_ALL);
    try {
      $result = call_user_func_array($callback, $arguments);
    } catch (Exception $ex) {
      restore_error_handler();
      error_reporting($orig_error_reporting);
      throw $ex;
    }
    restore_error_handler();
    error_reporting($orig_error_reporting);
    return $result;
  }
  function onError($severity, $message, $file = null, $line = null) {
    $this->errors[] = $message;
  }
  function getErrors() {
    return $this->errors;
  }
  function hasErrors() {
    return count($this->errors) > 0;
  }
}

E un caso d'uso:

$doc = new DomDocument();
$doc->load($xml_filename);
$validation = new errorhandler_LoggingCaller();
$validation->call(
  array($doc, 'schemaValidate'),
  array($xsd_filename));
if ($validation->hasErrors()) {
  var_dump($validation->getErrors());
}

Gli errori non gestiti fermano lo script, che da solo è un buon motivo per gestirli.

Generalmente puoi usare un blocco Try-Catch per gestire gli errori

try
{
    // Code that may error
}
catch (Exception $e)
{
    // Do other stuff if there's an error
}

Se si desidera interrompere la visualizzazione dell'errore o del messaggio di avviso sulla pagina, è possibile aggiungere un prefisso alla chiamata con un segno @ in questo modo.

 @mysql_query($query);

Con le query, tuttavia, è generalmente una buona idea fare qualcosa del genere in modo da avere un'idea migliore di ciò che sta accadendo.

@mysql_query($query)
    or die('Invalid query: ' . mysql_error() . '<br />Line: ' . __LINE__ . '<br />File: ' . __FILE__ . '<br /><br />');

Dovresti usare la Gestione degli errori nei casi in cui non hai il controllo esplicito sui dati su cui sta lavorando lo script. Tendo ad usarlo frequentemente, ad esempio in posti come la validazione di moduli. Sapere come individuare i punti soggetti a errori nel codice richiede un po 'di pratica: alcuni comuni sono dopo le chiamate di funzione che restituiscono un valore o quando si tratta di risultati da una query del database. Non dovresti mai supporre che il ritorno da una funzione sia quello che ti aspetti, e dovresti essere sicuro di programmare in anticipo. Non è necessario utilizzare i blocchi try / catch, sebbene siano utili. Molte volte puoi cavartela con un semplice controllo if / else.

La gestione degli errori va di pari passo con le pratiche di codifica sicura, in quanto vi sono molti "errori". ciò non causa l'arresto anomalo del tuo script. pur non trattandosi strettamente della gestione degli errori in sé, addbytes ha una buona serie di 4 articoli su alcune delle basi della programmazione PHP sicura che puoi trovare QUI . Ci sono molte altre domande qui su StackOverflow su argomenti come mysql_real_escape_string e Espressioni regolari che possono essere molto potenti nel confermare il contenuto di dati inseriti dall'utente.

La migliore pratica IMHO è usare il seguente approccio: 1. creare un gestore errori / eccezioni 2. avviarlo all'avvio dell'app 3. gestisci tutti i tuoi errori dall'interno

<?php

debug di classe {

    public static setAsErrorHandler() {
         set_error_handler(array(__CLASS__, '__error_handler'));
    }

public static function __error_handler($errcode, $errmsg, $errfile, $errline) {
       if (IN DEV) {
                print on screen
           }
           else if (IN PRO) {
                log and mail
           } 
    }

}

Debug :: setAsErrorHandler ();

>?

Invece di emettere mysql_error, è possibile memorizzarlo in un registro. in questo modo è possibile tenere traccia dell'errore (e non dipendere dagli utenti per segnalarlo) e si può entrare e rimuovere il problema.

La migliore gestione degli errori è il tipo che è trasparente per l'utente, lascia che il tuo codice risolva il problema, non è necessario coinvolgere quell'utente.

oltre a gestire subito gli errori nel tuo codice, puoi anche utilizzare

http://us.php.net/manual /en/function.set-exception-handler.php
e
http://us.php.net/manual/en/ function.set-error-handler.php

Trovo particolarmente utile l'impostazione del proprio gestore eccezioni. Quando si verifica un'eccezione, è possibile eseguire diverse operazioni a seconda del tipo di eccezione.

es: quando una chiamata mysql_connet restituisce FALSE lancio un nuovo DBConnectionException (mysql_error ()) e lo gestisco come " special " modo: registra l'errore, le informazioni di connessione al DB (host, nome utente, password) ecc. e magari invia un'e-mail al team di sviluppo notificando loro che qualcosa potrebbe davvero non funzionare nel DB

Lo uso per complimentarmi con la gestione degli errori standard. non consiglierei un uso eccessivo di questo approccio

La soppressione degli errori con @ è molto lenta.

Puoi anche utilizzare i moduli di Google per rilevare e analizzare le eccezioni, senza dover mantenere un database o un server accessibile pubblicamente. C'è un tutorial qui che spiega il processo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top