2017-12-04 4 views
-1

So habe ich dieses OOP Login & Registersystem, das einem Benutzer die Möglichkeit gibt, seinen/ihren Namen zu ändern.versuchen und fangen zur gleichen Zeit ausgeführt

Wenn ein Benutzer die Schaltfläche "Update" drückt, wird sein Name in der DB geändert. Das Problem ist, dass er den Namen in der DB ändert, anstatt den Benutzer dorthin umzuleiten, wo ich ihn umleiten soll Fehler, der nur angezeigt werden sollte, wenn dieser Name nicht geändert werden konnte.

User.php

<?php 

class User{ 
private $_db, 
     $_data, 
     $_sessionName, 
     $_cookieName, 
     $_isLoggedIn; 

public function __construct($user = null){ 
    $this->_db = DB::getInstance(); 

    $this->_sessionName = Config::get('session/session_name'); 
    $this->_cookieName = Config::get('remember/cookie_name'); 

    if(!$user){ 
     if(Session::exists($this->_sessionName)){ 
      $user = Session::get($this->_sessionName); 

      if($this->find($user)){ 
       $this->_isLoggedIn = true; 
      } else{ 
       //process logout 
      } 
     } 
    } else{ 
     $this->find($user); 
    } 
} 

public function update($fields = array(), $id = null){ 

    if(!$id && $this->isLoggedIn()){ 
     $id = $this->data()->id; 
    } 

    if(!$this->_db->update('users', $id, $fields)){ 
     throw new Exception('There was a problem updating your profile.'); 
    } 
} 

public function create($fields = array()){ 
    if(!$this->_db->insert('users', $fields)){ 
     throw new Exception('There was a problem creating an account'); 
    } 
} 

public function find($user = null){ 
    if($user){ 
     $field = (is_numeric($user)) ? 'id' : 'username'; 
     $data = $this->_db->get('users', array($field, '=', $user)); 

     if($data->count()){ 
      $this->_data = $data->first(); 
      return true; 
     } 
    } 
    return false; 
} 

public function login($username = null, $password = null, $remember = false){ 
    if(!$username && !$password && $this->exists()){ 
     Session::put($this->_sessionName, $this->data()->id); 
    } else{ 
     $user = $this->find($username); 
     if($user){ 
      if($this->data()->password === Hash::make($password, $this->data()->salt)){ 
       Session::put($this->_sessionName, $this->data()->id); 

       if($remember){ 
        $hash = Hash::unique(); 
        $hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id)); 

        if(!$hashCheck->count()){ 
         $this->_db->insert('users_session',array(
          'user_id' => $this->data()->id, 
          'hash' => $hash 
         )); 
        } else{ 
         $hash = $hashCheck->first()->hash; 
        } 
        Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry')); 
       } 

       return true; 
      } 
     } 
    } 
    return false; 
} 

public function exists(){ 
    return(!empty($this->_data)) ? true : false; 
} 

public function logout(){ 
    $this->_db->delete('users_session', array('user_id', '=', $this->data()->id)); 

    Session::delete($this->_sessionName); 
    Cookie::delete(Config::get('remember/cookie_name')); 
} 

public function data(){ 
    return $this->_data; 
} 

public function isLoggedIn(){ 
    return $this->_isLoggedIn; 
} 
} 

edit-profile.php

<?php 

    $user = new User(); 
    if(!$user->isLoggedIn()){ 
     Redirect::to('login'); 
    } 

    if(Input::exists()){ 
     if(Token::check(Input::get('token'))){ 

      $validate = new Validate(); 
      $validation = $validate->check($_POST, array(
       'name' => array(
        'required' => true, 
        'min' => 2, 
        'max' => 50 
       ) 
      )); 

      if($validation->passed()){ 

       try{ 
        $user->update(array(
         'name' => Input::get('name') 
        )); 

        Session::flash('flash', 'Your profile has been edited with success!'); 
        Redirect::to('flash'); 

       } catch(Exception $e){ 
        die($e->getMessage()); 
       } 
      } else{ 
       foreach($validation->errors() as $error){ 
        echo $error . '<br />'; 
       } 
      } 

     } 
    } 

    ?> 

    <form action="" method="post"> 
     <div class="field"> 
      <input type="text" name="name" value="<?php echo escape($user->data()->name); ?>"> 
     </div> 
     <input type="submit" value="Update"> 
     <input type="hidden" name="token" value="<?php echo Token::generate(); ?>"> 
    </form> 

Ich habe keine Ahnung, warum das

Dies ist die update() -Methode geschieht in meine DB.class

public function update($table, $id, $fields){ 
     $set = ''; 
     $x = 1; 

     foreach ($fields as $name => $value) { 
      $set .= "{$name} = ?"; 
      if($x < count($fields)){ 
       $set .= ', '; 
      } 
      $x++; 
     } 

     $sql = "UPDATE {$table} SET {$set} WHERE id = {$id}"; 

     if($this->query($sql, $fields)->error()){ 
      return true; 
     } 
     return false; 
    } 
+0

was ist das? 'DB :: getInstance()' Ich meine ich weiß, was es ist (Singleton), aber ist es eine Bibliothek oder etwas, im Grunde ist das die Rückkehr für das Update. Das ist eine Menge statischer Anrufe drin .... – ArtisticPhoenix

+0

Ich meine auf der Oberfläche sieht es ok aus, nicht sicher, ich würde es so machen, aber ... – ArtisticPhoenix

+0

DB.php ist meine DB-Klasse. ich kann es nicht als ein Kommentar anscheinend hinzufügen ... Update-Methode ist im Grunde das: öffentliche Funktion Update ($ Tabelle, $ ID, $ Felder) { \t \t $ set = ''; \t \t $ x = 1; \t \t foreach ($ Felder wie Name $ => $ value) { \t \t \t $ set = "{$ name} =?". \t \t \t if (x $ query ($ sql, $ Felder) -> Fehler()) { \t \t \t return true; \t \t} \t \t Rückgabe false; \t} – emma

Antwort

0

Für Ihre Update-Funktion

public function update($table, $id, $fields){ 
    $set = ''; 
    $x = 1; 
    foreach ($fields as $name => $value) { 
     $set .= "{$name} = ?"; 
     if($x < count($fields)){ 
      $set .= ', '; 
     } 
     $x++; 
    } 
    $sql = "UPDATE {$table} SET {$set} WHERE id = {$id}"; 
    if($this->query($sql, $fields)->error()){ 
     return true; 
    } 
    return false; 
} 

Statt

public function update($table, $id, $fields){ 

    $set = []; 

    foreach ($fields as $name => $value) { 
     $set[] = "{$name} = ?"; 
    } 

    $set = implode(', ', $set); 

    $sql = "UPDATE {$table} SET {$set} WHERE id = ?"; 
    $fields[] = $id; //id should always be the last ? 
    if($this->query($sql, $fields)->error()){ 
     return true; 
    } 
    return false; 
} 

auch tun gibt es das Potenzial für die table und id und auch die Schlüssel von $fields als Vektor für SQL-Injektion verwendet werden. Sie können es dort eingeben, wo immer Sie es verwenden. Aber es ist möglich, weil Sie die Tabelle nicht mit einer weißen Liste vergleichen und wann immer Sie Werte in SQL verketten, besteht die Möglichkeit, dass sie ausgenutzt werden. Alles was es braucht, ist ein Fehler, Ihre Klasse sollte keine Codierungsfehler an anderen Stellen zulassen, um die Sicherheit zu gefährden.

Sie können eine Liste von Tabellen aus der Datenbank selbst erhalten.

$statement = 'SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` LIKE "'.$database.'"'; 

Also, wenn Sie an die DB verbinden können Sie eine Liste der zulässigen Tabellen dann überprüfen, wenn eine Tabelle in (mit in_array oder so) gesetzt wird. Nur ein Gedanke.

Es kann auch möglich sein, die Schlüssel des $fields Array zu umfassen, für die Sie etwas Ähnliches wie die Tabelle tun können. aber mit dieser Abfrage

SHOW COLUMNS FROM {table} 

Zum Beispiel vorstellen, eine Post-Anforderung, die $fields Eingänge für Ihre Array hat. Alles, was Sie tun müssten, ist, Ihrem Server eine Anfrage mit dem SQL Attack Teil im Schlüssel anstelle des Wertes zu senden, und Sie sind ungeschützt. So etwas wie diese (nicht fallen Ihre DB nicht ohne Backup, das Gefühl, ich sollte sagen.)

$_POST['1=1; DROP DATABASE --'] = true; 

Wenn Sie Ihre Abfrage erstellen Sie

INSERT INTO table SET 1=1; DROP DATABASE -- = ?, {field} = ? .. rest of query 

Die -- startet einen Kommentar in SQL haben würde so nichts nach der -- Angelegenheit der DB dies verhindert, dass ein Fehler passiert .. Also vorsichtig sein nur Dumping Post Schlüssel in Ihre SQL Ich bin nicht sicher, 1=1 würde funktionieren, aber sie könnten ein Feld aus der Liste der Eingabe genauso einfach . Dies ist nur zum Beispiel Zwecke.

Für mich ist diese Linie

if($this->query($sql, $fields)->error()){ 
     return true; 
    }else{ 
     return false; 
    } 

sagt, wenn ein Fehler Rückkehr ist true nicht sicher, ob das der Fall ist, wie ich weiß nicht, was $this->query oder ->error() ist aber ich glaube, $this->query muss $this oder einige Rück Objekt, das den Fehler enthalten würde. Es ist nur so verwirrend formuliert.

+0

O Gott ... ok, also danke, dass du mir diese Zeile gezeigt hast if ($ this-> query ($ sql, $ fields) -> error()) .... Ich habe nur vergessen diesen logischen Operator "!" ... ich habe es einfach hinzugefügt und jetzt funktioniert es so schön. Danke sooo sooo viel>: D < – emma

+0

Sure bitte beachten Sie meine Warnungen auf SQL Injection, schrieb ich eine ähnliche DB-Klasse für PDO mit den beiden Abfragen oben, um die Eingabe-Schlüssel und die Tabelle zu bereinigen. Als Bonus sagt 'SHOW COLUMNS' Ihnen, welches Feld der Primärschlüssel ist. – ArtisticPhoenix

+0

hmm, ich benutze diese Funktion, um Eingaben zu entkommen: function escape ($ string) { \t return htmlentities ($ string, ENT_QUOTES, 'UTF-8'); }. Wird das nicht die Arbeit machen? : -s – emma

Verwandte Themen