Używam Zend_Db_Adapter, a konkretnie Zend_Db_Adapter_Pdo_Abstract. Wyobrażam sobie, że ten problem dotyczy również innych adapterów. Kiedy PDOException jest rzucany, jest „nieprzechwycony”, aw wielu przypadkach ślad stosu ujawnia nazwę użytkownika i hasło.

Sprawdziłem, że wszystkie następujące wyjątki PDO pokazują poświadczenia w śladzie stosu:

  • SQLSTATE[HY000] [2005] Nieznany host serwera MySQL ...snip...
  • SQLSTATE[HY000] [2013] Utracono połączenie z serwerem MySQL podczas „odczytu pakietu autoryzacyjnego”
  • SQLSTATE[08004] [1040] Za dużo połączeń
  • SQLSTATE[28000] [1045] Odmowa dostępu dla użytkownika ...snip... (przy użyciu hasła: YES)

Moje witryny produkcyjne nie wyświetlają śladów stosu, gdy występują błędy, i nadal chcę widzieć ślady stosu dla tych błędów w moich środowiskach programistycznych. Po prostu nie chcę, aby nazwy użytkowników i hasła były wyświetlane w sposób przejrzysty.

4
Sonny 14 luty 2012, 18:49

2 odpowiedzi

Najlepsza odpowiedź

Rozwiążę to, nie rozwiązując tego... Pozwólcie, że wyjaśnię:

Obecnie nie ma możliwości wyłączenia śledzenia stosu z nieprzechwyconych wyjątków. PHP Ci na to nie pozwala.

Więc zamiast próbować go wyłączyć, po prostu nie pozwoliłbym, aby wyjątek pozostał niezauważony... Zainstalowałbym obsługa wyjątków, który następnie loguje informacje o śladach wstecznych. Nie wyświetlałbym tego na ekranie. Nie sprawdzałbym, w jakim środowisku się znajduje. Nie sprawdzałbym informacji o żądaniu. Po prostu zalogowałbym go do pliku i wyświetlił ogólną stronę błędu serwera 500.

Teraz w swoim module obsługi możesz selektywnie wyświetlać informacje o wywołaniu, dzięki czemu możesz wybrać, czy chcesz rejestrować informacje o argumencie:

set_exception_handler(function($exception) {
    $log = array(
        'message' => $exception->getMessage(),
        'trace' => array(),
    );
    foreach ($exception->getTrace() as $item) {
        $trace = isset($item['class']) ? $item['class'] . $item['type'] : '';
        $trace .= $item['function'] . '()';
        $log['trace'][] = $trace;
    }
    save_to_log($log);
});

Ale traktuję niewyłapany wyjątek jako znak błędu w twojej aplikacji. Powinieneś je znaleźć i naprawić. Jeśli zdobędziesz je na tyle, że martwisz się o przedstawienie argumentów na stronie, to naprawdę musisz naprawić fakt, że istnieją nieprzechwycone wyjątki w pierwszej kolejności...

Edytuj Oto demonstracja tego, co się dzieje:

class Foo {
    public function doSomething($user, $password) {
        throw new Exception('Something Went Wrong!');
    }
}

$f = new Foo();

$f->doSomething('user', 'passw');

Wyniki w CodePadzie:

<br />
<b>Fatal error</b>:  Uncaught exception 'Exception' with message 'Something Went Wrong!' in /code/MxH9Ls:4
Stack trace:
#0 /code/MxH9Ls(10): Foo-&gt;doSomething('user', 'passw')
#1 {main}
  thrown in <b>/code/MxH9Ls</b> on line <b>4</b><br />

Ale z obsługą wyjątków (zmodyfikowaną do drukowania zamiast dziennika):

set_exception_handler(function($exception) {
    $log = array(
        'message' => $exception->getMessage(),
        'trace' => array(),
    );
    foreach ($exception->getTrace() as $item) {
        $trace = isset($item['class']) ? $item['class'] . $item['type'] : '';
        $trace .= $item['function'] . '()';
        $log['trace'][] = $trace;
    }
    echo $log['message'] . "\n";
    foreach ($log['trace'] as $trace) {
        echo " - $trace\n";
    }
});

class Foo {
    public function doSomething($user, $password) {
        throw new Exception('Something Went Wrong!');
    }
}

$f = new Foo();

$f->doSomething('user', 'passw');

W CodePad generuje:

Something Went Wrong!
 - Foo->doSomething()
3
ircmaxell 14 luty 2012, 19:45

Można spróbować dwóch rzeczy, pierwszym i prawdopodobnie najlepszym rozwiązaniem byłoby przechwycenie wyjątków i przekazanie ich do niestandardowej klasy wyjątków. Klasa brałaby również instancję adaptera na wzór:

Nieprzetestowany przykład

class myPDOException extends Exception
{
     public function __construct($message = '', $code = 0, Exception $previous = null, Zend_Db_Adapter_Abstract $adapter) {
        $config = $adapter->getConfig();
        $message = str_replace(array($config['username'], $config['password']), array('--user--', '--pass--'));
        parent::__construct($message, $code, $previous);
     }         
}

Inną opcją byłoby użycie set_exception_handler po sprawdzeniu w swoim programie początkowym, czy środowisko jest programistyczne, wtedy możesz wykonać następujące czynności;

function exception_handler($exception) {
    if ($exception instanceof PDOException) {
        //load your configuration
        //replace the user pass in the message
        //rethrow the exceptio with the updated message
    }
}

set_exception_handler('exception_handler');

Sposób, w jaki radzę sobie z nieprzewidzianymi wyjątkami, polega na zapisaniu ich w kolejce, która następnie prześle mi wszystkie niezbędne informacje i możemy naprawić przyczynę wyjątku.

Mam nadzieję, że to pomoże

Sójka

1
Jason Brumwell 14 luty 2012, 19:20