用于安全删除数据库条目的我的Codeigniter方法

时间:2011-06-07 17:03:44

标签: php mysql database codeigniter

我一直在搜索在Codeigniter中删除数据库条目,我最终创建了一个我认为安全的解决方案。我真的很感激任何反馈!我不确定我是否正确行事......

优点:

  • 使用POST请求

  • 要删除的条目ID是
    验证

  • 使用CSRF保护(自动
    由Codeigniter生成)

在我的示例中,我删除了用户提交的链接(数据库表行包含链接标题,链接URL,链接描述)。

HTML:数据库entires包含在表单中。每个条目都有一个表单按钮,其中id属性中包含相应的链接ID。

<?php echo form_open('profile/remove_link'); ?>

<?php echo form_hidden('link_id', ''); //value will be populated via jquery ?>

<ul id="user_links">
    <?php foreach($query as $row): ?>

    <li><?php echo $row->link_title; ?></li>
    <li><?php echo auto_link($row->link_url, 'url', TRUE); ?></li>
    <li><?php echo $row->link_description; ?></li>

    <button type="submit" class="remove" id="<?php echo $row->link_id ?>"  value="remove">Remove Link</button>

    <?php endforeach; ?>
</ul>

</form>

JQUERY:当用户点击remove按钮时,相应的链接ID将添加到名为link_id的隐藏文本输入中。

$(document).ready(function(){
    $('.remove').click(function() {
        var link_to_remove = $(this).attr("id");
        $("input[name=link_id]").val(link_to_remove);
    }); 
}); 

点击删除按钮后,会将要删除的链接ID发送到控制器profile并运行remove_link

    function remove_link()
    {
        $this->load->model('Profile_model');
        $links_data['query'] = $this->Profile_model->links_read(); //get links from db to add in view

        //Validation
        $this->form_validation->set_rules('link_id', 'Link ID', 'trim|required|xss_clean|max_length[11]|numeric'); //validate link id

        if ($this->form_validation->run() == FALSE) //if validation rules fail
        {           
            $this->load->view('profile/edit_links_view', $links_data);
        }
        else //success
        {
            $link_id =  $this->input->post('link_id'); //get id of link to be deleted
            $seg = 'user_links'; //used to redirect back to user links page
            $this->Profile_model->links_delete($link_id, $seg); //send link id to model function            
        }       
    }

模型

    function links_delete($link_id, $seg)
    {
        $this->db->where('user_id', $this->tank_auth->get_user_id());
        $this->db->where('link_id', $link_id);
        $this->db->delete('user_links'); 
        redirect("/profile/$seg/");         
    }

3 个答案:

答案 0 :(得分:1)

我唯一看错的是你没有验证谁能够和不能删除记录。这是你应该关注的唯一问题。检查发送删除请求的人是否被允许执行此类操作的权限。除此之外,这只是一个偏好问题。

答案 1 :(得分:1)

如果数据库中的ID是唯一整数,则可以删除这些规则:

  

修剪| xss_clean |数字

并添加以下内容:

  

is_natural_no_zero

     

如果表单元素包含除自然数之外的任何内容但不包含零,则返回FALSE:1,2,3等。

numeric rule允许你可能不想要的一些字符,如小数和负数。这是源(一行):

return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);

如果出于某种原因,你在验证之前回复HTML输出中的输入,或者只是偏执,那么一定要:xss_clean it up。否则它并不是真的需要,因为我认为没有任何可能的XSS攻击方法只使用一个数字。

参考:

此外,您可能希望在查询中添加LIMIT 1子句,并确保从模型中返回一个值(可能为TRUE / FALSE),以便您知道查询是否成功,因此您可以向用户提供反馈,而不是假设一切顺利。

答案 2 :(得分:1)

我建议重写一下控制器和模型,使流程更合理,并提供更好的性能:

控制器:

function remove_link()
{
    if ($this->input->post('link_id'))
    {
         //Validation
         $this->form_validation->set_rules('link_id', 'Link ID', 'is_natural_no_zero');
         if ($this->form_validation->run())
         {
             $seg = 'user_links'; //do you really need to assign it to variable ??
             $this->load->model('Profile_model');
             if ($this->Profile_model->links_delete($this->input->post('link_id')) //send link id to model function
             {
                 redirect('/profile/user_links'); // redirect user in controller and only when model returns true
             }else{
                 // inform user about error somehow, eg. by setting session flashdata and redirecting back to /profile/user_links
             }
        } 
    } // else statement here was a mistake as in case of form_validation failure nothing happened
    $this->load->model('Profile_model');
    $links_data['query'] = $this->Profile_model->links_read(); //get links from db to add in view
    $this->load->view('profile/edit_links_view', $links_data);
}

模型:

function links_delete($link_id)
{
    $this->db->where('user_id', $this->tank_auth->get_user_id())
             ->where('link_id', $link_id)
             ->delete('user_links'); // you can chain methods without writing always $this->db->
    return $this->db->affected_rows(); // returns 1 ( == true) if successfuly deleted
}

作为jQuery代码中的旁注,我建议使用$('#some_id')而不是$('input [name = XXXX]') - 它可以节省一些javascript代码执行,因此更快