我正在从我不时使用的框架配置登录表单。但是,由于某种原因,$tryagain
错误仍然存在。我知道我的数据库中的信息是正确的,我甚至在数据库中编辑了密码以删除哈希以消除这个问题。
有没有人知道为什么它再次抛出尝试错误说信息有误?我可以注册用户,然后将其重定向到此页面以允许他们登录,因此登录是唯一的问题。
如果您需要框架中的更多代码,请告诉我们。我不想发布大量代码。
ini_set('display_errors', 1);
error_reporting(E_ALL);
require_once 'core/init.php';
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$remember = (Input::get('remember') === 'on') ? true : false;
$login = $user->login(Input::get('username'), Input::get('password'), $remember);
//var_dump($login);
if($login) {
Redirect::to('index');
} else {
echo $tryagain = '<span class="signinpanel">' . "The information you entered did not match our records." . '</span>';
}
} else {
foreach($validation->errors() as $error) {
echo $error, '<br>';
}
}
}
}
表格
<?php
if(Session::exists('home')) {
echo '<p>' . Session::flash('home') . '</p>';
}
?>
<form name="Sign In" action="" method="POST" autocomplete="on" accept-charset= "utf-8">
<div class="field">
<label for="username">Username</label>
<input type="text" name="username" autocomplete="on" required>
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" name="password" autocomplete="off" required>
</div>
<div class="field">
<label for="remember">
<input type="checkbox" name="remember" id="remember"> Remember me
</label>
</div><br>
<input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
<input type="submit" value="Sign In">
</form>
登录功能
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;
}
哈希文件
class Hash {
public static function make($string, $salt = '') {
return hash('sha256', $string . $salt);
}
public static function salt($length) {
return mcrypt_create_iv($length);
}
public static function unique() {
return self::make(uniqid());
}
}
答案 0 :(得分:1)
我认为您的错误在于您在此处进行的检查:
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
如果我正确读取了这个,你正在获取用户输入的值,然后创建一个全新的密码哈希值,并输入一个新的随机盐。每次代码执行时该值都会改变但是(非常)不太可能与输入密码相同。
最初这个答案是基于Laravel库:
而不是使用Hash:make
使用Hash::check
作为进入该区块的守卫:
if(Hash::check($this->data()->password, $password)){
Session::put($this->_sessionName, $this->data()->id);
这应该让login()
函数返回true
。
然而,由于@becky表示他们没有使用Laravel,因此需要更一般的答案:
您遇到的根本问题是您要根据加密(哈希)密码检查明文密码。在所有优秀的算法中,这不会是同样的事情,这就是为什么它永远不会从函数中返回真实。
您需要做的是检查用户输入内容的散列版本:Hash::make($password, $this->data()->salt)
,其中包含您已存储的值(因为您只存储散列版本)。如果您可以更改代码以比较这两个值,则它们应该相同,因此身份运算符===
将返回true
值。
进一步的讨论和一些调试表明,从数据库返回的内容并不是
在页面上创建的内容。Hash::make($password, $this->data()->salt)
语句。仔细观察后发现,db上列的长度已从64个字符减少到50.由于Hash::make()
函数返回了64个字符的哈希值,因此两者永远不会相等。重新构建该DB列并重新生成密码哈希解决了问题。