2017-12-04 3 views
-1

だから私はこのOOPログイン&ユーザーが彼/彼女の名前を変更する機能を与える登録システムを持っています。同時に試してキャッチを実行する

ユーザーが「更新」ボタンを押すと、DB内の名前が変更されます。問題は、リダイレクトするユーザーをリダイレクトするのではなく、DB内の名前を変更することです。その名前を変更できなかった場合にのみ表示されるエラーです。

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; 
} 
} 

<?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> 

私は

これが起こっている理由は見当もつかないが、update()メソッド内で編集profile.php私のDB.class

代わりに

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; 
} 

を行い、あなたの更新機能

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

これはなに? 'DB :: getInstance()'私はそれが何であるかを知っていることを意味しますが(シングルトン)、それはライブラリなどです。それはそこに静的な呼び出しの多くです.... – ArtisticPhoenix

+0

私はそれがこのように行うだろうかわからない、大丈夫に見える表面上を意味するが... – ArtisticPhoenix

+0

DB.phpは私のDBクラスです。私はコメントとしてコメントを追加することはできません...更新方法は基本的にはこれです: パブリック関数の更新($ table、$ id、$ fields){ \t \t $ set = ''; \t \t $ x = 1; \t \t foreachの($名として$フィールド=> $値){ \t \t \t $セット= "$ {名} =?"。 \t \t \t IF($ X <カウント($フィールド)){$ \t \t \t \t設定= ''。 \t \t \t} \t \t \t $ x ++; \t \t} \t \t $のSQL = "UPDATE {$表}集合{$セット} ID = {$のID}"。 \t \t場合(の$ this - >クエリ($ sqlを、$フィールド) - >エラー()){ \t \t \tリターンはtrue。 \t \t} \t \t return false; \t} – emma

答えて

0

はまた、SQLインジェクションのためのベクターとして使用するtableid$fieldsのも、鍵の可能性があります。これまでに使用した場所に入力している可能性があります。しかし、ホワイトリストと比較してテーブルをチェックしていないため、SQLに値を連結するたびに、それらが悪用される可能性があります。それが取るのは間違い1つですが、他の場所でのコーディングエラーでセキュリティが損なわれることは許されません。

データベース自体からテーブルのリストを取得できます。

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

だから、あなたがDBに接続するときには、許容可能なテーブルのリストを設定することができ、テーブルが(in_arrayかなと)に置かれたときに確認してください。ちょっとした考え。

$fields配列のキーを含むこともできます。これは、表と似たようなことができるからです。しかし、例えば、このクエリ

SHOW COLUMNS FROM {table} 

で、あなたの配列$fieldsに一致する入力を持つPOSTリクエストを想像してみてください。誰かが行う必要があるのは、値の代わりにキーにSQL Attackの部分を含むリクエストを送信することです。あなたは保護されません。このような何か(私はそれを言うべき感じ、バックアップせずにDBをドロップしません。)

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

あなたのクエリを作成しますが

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

--はSQLでコメントを開始しています何もないので、--のDBに関係しているので、エラーが発生するのを防ぐことができます。ちょうどあなたのSQLにポストキーをダンプすることに注意してください。1=1がうまくいくかはわかりませんが、 。これは単なる例示である。その場合は、私が何であるかを$this->query->error()知りませんが、私が想像するよう$this->query$thisまたは一部を返さなければなら必ずエラーリターンtrueないがあるかどうか私には

このライン

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

は言いますエラーを含むオブジェクト。それはちょうど混乱の言葉をその方法です。

+0

O god ... ok($ this-> query($ sql、$ fields) - > error())なら、この行を表示していただきありがとうございます....基本的に私はこの論理演算子 "!"を追加するのを忘れていました。 ...私はちょうどそれを追加し、今それはとても美しく動作します。 DOO – emma

+0

SQLインジェクションに関する私の警告に注意してください。上記の2つのクエリを使用してPDO用の同様のDBクラスを作成し、入力キーとテーブルをサニタイズしました。ボーナスとして 'SHOW COLUMNS'はプライマリキーがどのフィールドであるかを示します。 – ArtisticPhoenix

+0

hmm、私は入力をエスケープするためにこの関数を使用しています:function escape($ string){ \t return htmlentities($ string、ENT_QUOTES、 'UTF-8'); }。これは仕事をするつもりはないのですか? :-s – emma

関連する問題