所以我有这个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;
}
}
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>
我不知道为什么会发生这种情况
这是我的DB.class中的update()方法
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 :(得分:0)
用于更新功能
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;
}
取而代之的是
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;
}
此外,table
和id
甚至$fields
的键都可能被用作SQL注入的向量。您可能会在使用它们的地方输入它。但这是可能的,因为您没有根据白名单检查表,并且无论何时将值连接到SQL,都有可能被利用。所需要的只是一个错误,你上课时不应该允许其他地方的编码错误来破坏它的安全性。
您可以从数据库本身获取表格列表。
$statement = 'SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` LIKE "'.$database.'"';
因此,当您连接到数据库时,您可以设置可接受表的列表,然后检查何时放入表(使用in_array
等)。只是一个想法。
也可以包含$fields
数组的键,因为您可以执行类似于表的操作。但是有了这个查询
SHOW COLUMNS FROM {table}
例如,假设一个帖子请求的输入与您的数组$fields
匹配。所有人都必须做的是向服务器发送一个请求,其中包含密钥中的SQL Attack
部分而不是值,并且您不受保护。这样的事情(不要在没有备份的情况下放弃你的数据库,我觉得我应该这样说。)
$_POST['1=1; DROP DATABASE --'] = true;
构建查询时,您将拥有
INSERT INTO table SET 1=1; DROP DATABASE -- = ?, {field} = ? .. rest of query
--
在SQL中启动注释,因此在--
之后没有任何内容可以防止发生错误。所以要小心只是将post键转储到SQL中。我不确定1=1
是否可行,但他们可以轻松地使用输入列表中的字段。这只是为了举例。
给我这一行
if($this->query($sql, $fields)->error()){
return true;
}else{
return false;
}
如果错误返回true
,请确定是否是这种情况,因为我不知道$this->query
或->error()
是什么,但我想{{1}必须返回$this->query
或一些包含错误的对象。它只是令人困惑的措辞。