support hashing passwords with password_hash()

This commit is contained in:
printempw 2017-01-08 12:49:32 +08:00
parent c018e132c8
commit 7d9535007e
14 changed files with 95 additions and 33 deletions

View File

@ -30,9 +30,10 @@ DB_PREFIX = null
# Encrypt Method for Passwords. # Encrypt Method for Passwords.
# #
# Available values: MD5, SALTED2MD5, (SALTED2)SHA256, (SALTED2)SHA512 # Available values: PHP_PASSWORD_HASH, (SALTED2)MD5, (SALTED2)SHA256, (SALTED2)SHA512
# New sites are highly recommend to use PHP_PASSWORD_HASH.
# #
PWD_METHOD = SALTED2MD5 PWD_METHOD = PHP_PASSWORD_HASH
# Salt # Salt
# Change it to any random string to secure your passwords & tokens. # Change it to any random string to secure your passwords & tokens.

View File

@ -49,7 +49,7 @@ class AuthController extends Controller
if (!$user) { if (!$user) {
return json(trans('auth.validation.user'), 2); return json(trans('auth.validation.user'), 2);
} else { } else {
if ($user->checkPasswd($request->input('password'))) { if ($user->verifyPassword($request->input('password'))) {
Session::forget('login_fails'); Session::forget('login_fails');
Session::put('uid' , $user->uid); Session::put('uid' , $user->uid);

View File

@ -79,7 +79,7 @@ class UserController extends Controller
'new_password' => 'required|min:8|max:16' 'new_password' => 'required|min:8|max:16'
]); ]);
if (!$this->user->checkPasswd($request->input('current_password'))) if (!$this->user->verifyPassword($request->input('current_password')))
return json(trans('user.profile.password.wrong-password'), 1); return json(trans('user.profile.password.wrong-password'), 1);
if ($this->user->changePasswd($request->input('new_password'))) if ($this->user->changePasswd($request->input('new_password')))
@ -93,7 +93,7 @@ class UserController extends Controller
'password' => 'required|min:8|max:16' 'password' => 'required|min:8|max:16'
]); ]);
if (!$this->user->checkPasswd($request->input('password'))) if (!$this->user->verifyPassword($request->input('password')))
return json(trans('user.profile.email.wrong-password'), 1); return json(trans('user.profile.email.wrong-password'), 1);
if ($this->user->setEmail($request->input('new_email'))) if ($this->user->setEmail($request->input('new_email')))
@ -106,7 +106,7 @@ class UserController extends Controller
'password' => 'required|min:8|max:16' 'password' => 'required|min:8|max:16'
]); ]);
if (!$this->user->checkPasswd($request->input('password'))) if (!$this->user->verifyPassword($request->input('password')))
return json(trans('user.profile.delete.wrong-password'), 1); return json(trans('user.profile.delete.wrong-password'), 1);
if ($this->user->delete()) { if ($this->user->delete()) {

View File

@ -69,26 +69,28 @@ class User extends Model
* @param string $rawPasswd * @param string $rawPasswd
* @return bool * @return bool
*/ */
public function checkPasswd($rawPasswd) public function verifyPassword($rawPasswd)
{ {
return (static::encryptPassword($rawPasswd, $this) == $this->password); // compare directly if any responses is returned by event dispatcher
if ($result = static::getEncryptedPwdFromEvent($rawPasswd, $this)) {
return ($result == $this->password);
}
return app('cipher')->verify($rawPasswd, $this->password, config('secure.salt'));
} }
/** /**
* Encrypt user's password. * Try to get encrypted password from event dispatcher.
* *
* @param string $rawPasswd * @param string $rawPasswd
* @param User $user * @param User $user
* @return mixed * @return mixed
*/ */
protected static function encryptPassword($rawPasswd, User $user) protected static function getEncryptedPwdFromEvent($rawPasswd, User $user)
{ {
$responses = event(new EncryptUserPassword($rawPasswd, $user)); $responses = event(new EncryptUserPassword($rawPasswd, $user));
return Arr::get($responses, 0, return Arr::get($responses, 0);
// encrypt with current cipher if no response is returned by the event dispatcher
app('cipher')->encrypt($rawPasswd, config('secure.salt'))
);
} }
/** /**
@ -112,7 +114,7 @@ class User extends Model
$user->save(); $user->save();
// save again with password // save again with password
$user->password = static::encryptPassword($password, $user); $user->password = static::getEncryptedPwdFromEvent($password, $user) ?: app('cipher')->hash($password, config('secure.salt'));
$user->save(); $user->save();
return $user; return $user;
@ -131,7 +133,7 @@ class User extends Model
if (isset($responses[0])) { if (isset($responses[0])) {
$this->password = $responses[0]; $this->password = $responses[0];
} else { } else {
$this->password = app('cipher')->encrypt($new_passwd, config('secure.salt')); $this->password = app('cipher')->hash($new_passwd, config('secure.salt'));
} }
return $this->save(); return $this->save();

View File

@ -8,6 +8,7 @@ use Validator;
use App\Events; use App\Events;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use App\Exceptions\PrettyPageException;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -49,7 +50,14 @@ class AppServiceProvider extends ServiceProvider
public function register() public function register()
{ {
// register default cipher // register default cipher
$this->app->singleton('cipher', "App\Services\Cipher\\".config('secure.cipher')); $className = "App\Services\Cipher\\".config('secure.cipher');
if (class_exists($className)) {
$this->app->singleton('cipher', $className);
} else {
exit(sprintf("No such encrypt method: [%s], please check your .env configuration.", config('secure.cipher')));
}
$this->app->singleton('users', \App\Services\Repositories\UserRepository::class); $this->app->singleton('users', \App\Services\Repositories\UserRepository::class);
$this->app->singleton('parsedown', \Parsedown::class); $this->app->singleton('parsedown', \Parsedown::class);
} }

View File

@ -0,0 +1,23 @@
<?php
namespace App\Services\Cipher;
abstract class BaseCipher implements EncryptInterface
{
/**
* {@inheritdoc}
*/
public function hash($value, $salt = "")
{
//
}
/**
* {@inheritdoc}
*/
public function verify($password, $hash, $salt = "")
{
return ($this->hash($password, $salt) === $hash);
}
}

View File

@ -5,11 +5,20 @@ namespace App\Services\Cipher;
interface EncryptInterface interface EncryptInterface
{ {
/** /**
* Encrypt given string w/ or w/o salt * Encrypt given string with given salt.
* *
* @param string $value * @param string $value
* @param string $salt * @param string $salt
* @return string * @return string
*/ */
public function encrypt($value, $salt = ""); public function hash($value, $salt = "");
/**
* Verifies that the given hash matches the given password.
*
* @param string $password
* @param string $hash
* @return bool
*/
public function verify($password, $hash);
} }

View File

@ -2,12 +2,12 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class MD5 implements EncryptInterface class MD5 extends BaseCipher
{ {
/** /**
* Once MD5 hash * Once MD5 hash
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return md5($value); return md5($value);
} }

View File

@ -0,0 +1,19 @@
<?php
namespace App\Services\Cipher;
class PHP_PASSWORD_HASH extends BaseCipher
{
/**
* Use password_hash() to create hash.
*/
public function hash($value, $salt = "")
{
return password_hash($value, PASSWORD_DEFAULT);
}
public function verify($password, $hash, $salt = "")
{
return password_verify($password, $hash);
}
}

View File

@ -2,12 +2,12 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class SALTED2MD5 implements EncryptInterface class SALTED2MD5 extends BaseCipher
{ {
/** /**
* MD5 hash with salt * MD5 hash with salt
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return md5(md5($value).$salt); return md5(md5($value).$salt);
} }

View File

@ -2,12 +2,12 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class SALTED2SHA256 implements EncryptInterface class SALTED2SHA256 extends BaseCipher
{ {
/** /**
* SHA256 hash with salt * SHA256 hash with salt
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return hash('sha256', hash('sha256', $value).$salt); return hash('sha256', hash('sha256', $value).$salt);
} }

View File

@ -2,14 +2,14 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class SALTED2SHA512 implements EncryptInterface class SALTED2SHA512 extends BaseCipher
{ {
/** /**
* SHA512 with salt * SHA512 hash with salt
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return hash('sha512', hash('sha256', $value).$salt); return hash('sha512', hash('sha512', $value).$salt);
} }
} }

View File

@ -2,12 +2,12 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class SHA256 implements EncryptInterface class SHA256 extends BaseCipher
{ {
/** /**
* Once SHA256 hash * Once SHA256 hash
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return hash('sha256', $value); return hash('sha256', $value);
} }

View File

@ -2,12 +2,12 @@
namespace App\Services\Cipher; namespace App\Services\Cipher;
class SHA512 implements EncryptInterface class SHA512 extends BaseCipher
{ {
/** /**
* Once SHA512 hash * Once SHA512 hash
*/ */
public function encrypt($value, $salt = "") public function hash($value, $salt = "")
{ {
return hash('sha512', $value); return hash('sha512', $value);
} }