我一直在搜索在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/");
}
答案 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代码执行,因此更快