我使用Codeigniter 3.1.3并在配置文件中启用了CSRF保护。不知何故,如果表单通过验证,我总是从ajax $ .post获得500(内部服务器错误)。如果验证失败,我没有收到该错误。有什么想法吗?
以下是codeigniter配置文件中的csrf设置:
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_token_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
以下是我在login.php视图中的登录表单:
<form id="login_form" class="col-12 col-md-8 mx-auto" method="post">
<div class="alert" id="login-alert" role="alert"></div>
<div class="form-group input-group">
<span class="input-group-addon" id="basic-addon1">Username</span>
<input type="text" class="form-control" id="username" name="username" />
</div>
<div class="form-group input-group">
<span class="input-group-addon" id="basic-addon2">Password</span>
<input type="password" class="form-control" id="pwd" name="pwd" />
</div>
<div class="text-center">
<button type="button" id="login_btn" class="btn btn-primary">LOGIN</button>
</div>
</form>
我使用AJAX $ .post提交表单
$("#login_btn").click(function(){
var data = $("#login_form").serialize();
var csrf_name = "<?=$this->security->get_csrf_token_name()?>";
//get_cookie is a function that I defined to retrieve the cookie
var csrf_cookie = get_cookie("csrf_cookie_name");
$.post('index.php/sentinel/verify_user',data+"&"+csrf_name+"="+csrf_cookie,function(data){
if(data && data !== '')
{
data = data.replace(/(<p>)/g,'').replace(/(<\/p>)/g,'<br>');
$("#login-alert").prop('class','alert alert-danger').html(data);
}
else
{
//success
//redirect to the main page
}
});
});
function get_cookie( check_name ) {
var a_all_cookies = document.cookie.split( ';' );
var a_temp_cookie = '';
var cookie_name = '';
var cookie_value = '';
var b_cookie_found = false; // set boolean t/f default f
for ( i = 0; i < a_all_cookies.length; i++ )
{
// now we'll split apart each name=value pair
a_temp_cookie = a_all_cookies[i].split( '=' );
// and trim left/right whitespace while we're at it
cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
// if the extracted name matches passed check_name
if ( cookie_name == check_name )
{
b_cookie_found = true;
// we need to handle case where cookie has no value but exists (no = sign, that is):
if ( a_temp_cookie.length > 1 )
{
cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
}
// note that in cases where cookie is initialized but no value, null is returned
return cookie_value;
break;
}
a_temp_cookie = null;
cookie_name = '';
}
if ( !b_cookie_found )
{
return null;
}
}
这是我的控制器:
public function verify_user(){
$this->form_validation->set_rules('username', 'Username', 'required|alpha');
$this->form_validation->set_rules('pwd', 'Password', 'required|callback_alpha_numeric_dots');
$this->form_validation->set_message('alpha_numeric_dots','Invalid Password.');
if ($this->form_validation->run() == FALSE)
{
echo validation_errors();
}
else
{
$this->form_validation->set_rules('pwd','Password','callback_login_check');
if ($this->form_validation->run() == FALSE)
{
echo validation_errors();
}
else
{
echo '';
}
}
}
public function login_check(){
$data = $this->security->xss_clean($this->input->post());
$rep_info= $this->sentinel_model->user_verify($data);
if($rep_info === FALSE)
{
$this->form_validation->set_message('login_check', 'Incorrect Username or Password');
return FALSE;
}
else
{
//set session data here
$newdata = array(
'id' =>$this->encryption->encrypt($rep_info['user_id']),
'name' => $rep_info['user_name'],
'email' => $rep_info['user_email'],
'logged_in' => TRUE
);
$this->session->set_userdata($newdata);
return TRUE;
}
}
public function alpha_numeric_dots($str)
{
return (bool) preg_match('/^[A-Z0-9.]+$/i', $str);
}
我还想在用户成功登录后将用户重定向到另一个视图而不更改网址。最好的方法是什么?
答案 0 :(得分:0)
当使用CSRF
函数及其快速修复时,form_open()
标记作为隐藏输入添加到表单中。
具有CSRF
标记值的cookie由Security
类创建,并在必要时为每个请求重新生成。
如果存在$_POST
数据,则Cookie会自动由输入类验证。如果发布的令牌与Cookie的值不匹配,CI
将显示错误,无法处理$_POST
数据。
所以基本上,它都是自动的 - 您只需在$config['csrf_protection']
中启用它,然后使用表单的form_open()
功能。
所以客户端你只需要发布
$.post('index.php/sentinel/verify_user',$("#login_form").serialize(),function(data){
});
在您的控制器中
$this->load->helper('form');
并在您查看文件
<?php echo form_open('sentinel/verify_user', 'id="login_form" class="col-12 col-md-8 mx-auto"'); ?>
<div class="alert" id="login-alert" role="alert"></div>
<div class="form-group input-group">
<span class="input-group-addon" id="basic-addon1">Username</span>
<input type="text" class="form-control" id="username" name="username" />
</div>
<div class="form-group input-group">
<span class="input-group-addon" id="basic-addon2">Password</span>
<input type="password" class="form-control" id="pwd" name="pwd" />
</div>
<div class="text-center">
<button type="button" id="login_btn" class="btn btn-primary">LOGIN</button>
</div>
</form>
或强>
在下面的表单中创建隐藏输入
<input type="hidden" name="<?php echo $this->security->get_csrf_token_name(); ?>" value="<?php echo $this->security->get_csrf_hash();?>" />
或强>
不修改视图文件,(已发布的更正版本)
var data = $("#login_form").serialize();
$.post(
'index.php/sentinel/verify_user',
data+"&" + '<?php echo $this->security->get_csrf_token_name(); ?>' +"="+ '<?php echo $this->security->get_csrf_hash(); ?>',
function(data){
});
发表评论
实际上我只是注意到我得到了403(Fordidden)错误 我第二次点击登录按钮
来自the docs:
标记可以在每次提交时重新生成(默认),也可以在CSRF cookie的整个生命周期内保持相同。标记的默认重新生成提供更严格的安全性,但可能导致可用性问题,因为其他标记变得无效(后退/前进导航,多个选项卡/窗口,异步操作等)。您可以通过编辑以下配置参数
来更改此行为$config['csrf_regenerate'] = TRUE;
将其设置为FALSE。