Consider the following class
class User
{
protected $password;
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getPassword()
{
return $this->password;
}
}
I want to apply bcrypt on password using Zend\Crypt\Password\Bcrypt in user object, since this creates a dependency i want to know how to correctly deal with this, i can think about several approaches to make this work, let me elaborate
Approach 1 : Here we instantiate the class inside the method and apply required changes.
class User
{
protected $password;
public function setPassword($password)
{
$bcrypt = new Bcrypt();
$this->password = $bcrypt->create($password);
return $this;
}
public function getPassword()
{
return $this->password;
}
public function verifyPassword($password)
{
$bcrypt = new Bcrypt();
return $bcrypt->verify($password, $this->getPassword());
}
}
Towards my understanding this is not recommended approach since i see two problems here
Bcrypt() is instantiated twice
This makes User object tightly coupled with Bcrypt
I can solve problem-1 by instantiating Bcrypt() once in class constructor and use it whenever required, however this does not solve problem-2
Approach 2 : Move Bcrypt object out of user class and inject it while setting the password
class User
{
protected $password;
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getPassword()
{
return $this->password;
}
}
// Init Bcrypt
$bcrypt = new Bcrypt;
// Instantiate user object and create a password
$user = new User;
$user->setPassword($bcrypt->create($password));
// Verify user password
if ($bcrypt->verify($password, $user->getPassword())) {
// Password is verified
}
What is the best way to about it ?
Thanks.
And maybe you can just create a Password class and move this logic there?
You can either do something like this:
class Password
{
private $password;
public __construct($password)
{
$this->password = $password;
}
public crypt(Zend_Crypt_Password_PasswordInterface $crypt)
{
$this->password = $crypt->create($password);
}
}
or use a Decorator.
Both solution gives you a possibility for extending your code.
Instead of Zend_Crypt_Password_PasswordInterface you can also use your own Wrapper. It would be IMHO even better solution.
And then you can set the password for particular user and it does not care whether it was crypted, hashed or whatever:
class User
{
private $password;
public function changePassword(Password $password)
{
$this->password = $password;
}
}
I guess first approach is better because its hide using of bcrypt within User class.
I dont think that other programmer have to keep in mind that he have to use, for example, $bcrypt->verify when working with User class.
Related
I have had this doubt for some time, because I don't know if I'm actually correctly encrypting the data, if I'm passing the correct values when instantiating the class and calling the function, and I also don't know if the return of the functions is correct, using password_hash
I believe it is correct, the hash works perfectly, but I would like to make sure that there is nothing wrong with my code, as I am a novice and object orientation can leave me a little confused
<?php
class SignUp {
private $email;
private $password;
public function setEmail($e) {
$this->email = $e;
}
public function getEmail() {
return $this->email;
}
public function setPassword($p) {
$this->password = $p;
}
public function getPassword() {
return $this->password = password_hash($_POST['password'], PASSWORD_BCRYPT);
}
}
$obj = new SignUp();
$obj->setEmail($_POST['email']);
$obj->setPassword($_POST['password']);
I'm new to OOP and very confused about it. A class that collected user info from database based on the ID passed though:
class user {
public $profile_data;
public function __construct($profile_user_id) {
$this->profile_data = user_data($profile_user_id, 'id', 'username', 'password', 'email', 'admin');
}
}
$profile_data[] = new user(1);
How do I get all the variables in the array? How do I echo out the username for example?
Simply try this.
class user {
public $profile_data;
public function __construct($profile_user_id) {
$this->profile_data = user_data($profile_user_id, 'id', 'username', 'password', 'email', 'admin');
}
}
$userObj = new user(1);
$profileData = $userObj->profile_data;
echo $profileData['username'];
Assuming your user_data function is returning an associative array of data, you should be able to access the fields using as such:
$profile = new user(1);
echo $profile->profile_data['username'];
As in Lighthart's example, it would be good practice to create private variables, with functions to access them.
Another option would be to implement the ArrayAccess interface (http://php.net/manual/en/class.arrayaccess.php) Using this interface, you would be able to use your object similarly to how you use an array. That is, you could use:
echo $user['username'];
As a starting point, you could try something like:
class user implements ArrayAccess {
private $data;
public function __construct($profile_user_id) {
$this->data= user_data($profile_user_id, 'id', 'username', 'password', 'email', 'admin');
}
public function offsetSet($offset, $value) {
// Do nothing, assuming non mutable data - or throw an exception if you want
}
public function offsetExists($offset) {
return isset($this->data[$offset]);
}
public function offsetUnset($offset) {
// Do nothing, assuming non mutable data - or throw an exception if you want
}
public function offsetGet($offset) {
return isset($this->data[$offset]) ? $this->data[$offset] : null;
}
}
The example you have given probably won't work for what you are trying to accomplish. It is not clear what function userdata does. Revised:
class User {
private $id;
private $username;
private $password;
private $email;
private $admin;
public function __construct($id, $username, $password, $email, $admin) {
$profileData = user_data($profile_user_id
,'id'
,'username'
,'password'
,'email'
,'admin');
$this->id = $profileData ['id'];
$this->username = $profileData ['username'];
$this->password = $profileData ['password'];
$this->email = $profileData ['email'];
$this->admin = $profileData ['admin'];
}
public function getId(){ return $this->id; }
public function getUsername(){ return $this->username; }
public function getEmail(){ return $this->email; }
public function getAdmin(){ return $this->admin; }
public function setAdmin($admin){ $this->admin = $admin; }
}
The variables are set private. Only the user object should have access to the data directly. However, other objects might want to retrieve the data, which is why there are 4 public get functions. getPassword was omitted because you probably don't want that one publicly available. Also, it is concievable you might set a new admin, so a public setter function was added as well. you would instance the new user (that is, take the class and make a real example of it) thusly:
$user1 = new User(1);
And during usage you would echo these variables by:
echo $user1->getUsername();
Please accept my apologies for not directly answering your question, but that example is headed for trouble.
I am using Yii framework and I want to create a user login system with rehashing passwords. so when user loges in system geerates new salt and rehashes the password with new salt. I am getting no errors but when I am checking password and salt they don't change in database. so here is what I have done for now:
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity
{
private $_id;
public function authenticate()
{
$record=User::model()->findByAttributes(array('username'=>$this->username));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->password !== hash('sha512', $this->password.Security::Decrypt($record->salt)))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
while ($record2 !== null){
$salt = Security::GenerateSalt(128);
if ($salt === null)
{
die('can\'t generate salt');
}
$record2 = User::model()->findByAttributes(array('salt'=>Security::Encrypt($salt)));
}
$record->salt = Security::Encrypt($salt);
$record->password = hash('sha512', $this->password.$salt);
$record->save();
$this->_id=$record->id;
$this->setState('user_id', $record->id);
$this->setState('user_username', $record->username);
$this->setState('user_privilages', $record->privilages);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
}
Use authenticate only to authenticate and return success or failure status
Use the AfterLogin method in the CWebUser class to perform the rehashing and make sure you do it only when authorized from username/password and not from cookie.
Your webuser class would look like this:
protected $plain_password;
public function login( $identity, $duration = 0)
{
// ...
$this->id = $identity->id;
$this->plain_password = $identity->password;
return parent::login($identity, $duration);
}
protected function afterLogin($fromCookie)
{
$this->updateUserDataOnLoginSuccess($fromCookie);
return parent::afterLogin($fromCookie);
}
/**
* If the user logged in successfuly, we should update some data about him, like the last login time
* #param bool $fromCookie indicates whether the login takes place using cookie or login form
*/
private function updateUserDataOnLoginSuccess($fromCookie)
{
$attributes = array('last_login' => new CDbExpression('NOW()'));
if(!$fromCookie)
{
$atrributes['hash'] = new hash;
$attributes['password'] = new hashedpassword($this->plain_password, $atrributes['hash']);
}
User::model()->updateByPk($this->id, $attributes);
}
This might look as a stupid question. But, I have a class with some public string variables defined in it.
Upon assigning a value to a property:
$a = new user();
$a->FirstName = "sth";
I want to store the value as UTF8.
I know I can do this via:
$a->Firstname = utf8_encode("sth");
However, I want the object to do this automatically.
How can I do this?
Otherwise no, the object cannot do it automatically.
Not automatically, but automagically!
<?php
class User {
/**
* Change the public to private/protected!
*/
private $Firstname;
/**
* This is automatically called upon calling a value that can't be written "from the outside".
*/
public function __set( $key, $value ) {
$this->$key = utf8_encode( $value );
}
public function __get( $key ) {
return isset( $this->$key ) ? $this->$key : false;
}
}
$user = new User;
$user->Firstname = 'Berry';
echo $user->Firstname;
The better solution would be to refactor in using mutators and accessors, or better yet, learn OO.
You want to use setters and getters. See: http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29
Like:
class User
{
protected $Firstname;
public function setFirstname($Firstname) {
$this->Firstname = utf8_encode($Firstname);
}
public function getFirstname() {
return $this->Firstname;
}
}
Example using magic methods:
class User
{
protected $data = array(
'Firstname' => '',
// ...
);
public function __set($key, $value) {
if (isset($this->data[$key])) {
$this->data[$key] = utf8_encode($value);
}
}
public function __get($key) {
return isset($this->data[$key]) ? $this->data[$key] : null;
}
}
Edit: I'm using $data so that there is at least a minimum of control of what properties can be set.
If you'd designed your class to have accessors and mutators, rather than public access to raw variables, then this would be easy.
Original code:
class user {
private $FirstName = '';
public function getFirstName() {
return $this->FirstName;
}
}
Solution code:
class user {
private $FirstName = '';
public function getFirstName() {
return utf8_encode($this->FirstName);
}
}
I suggest moving towards this approach.
Otherwise no, the object cannot do it automatically.
Edit
__set and __get might be the most appropriate way to implement this. I'm not too familiar with them, and it doesn't really matter: the point I'm making here is to use accessors and mutators... however you end up implementing them.
I have a users model that has a lot of properties such as first_name, last_name, email, address, address2...etc
I am writing a php class to manage these properties, but it seems like I am writing a lot of the same code. (Getters and setters). Should I use magic methods to manage this? It seems like an OK idea, but I don't want incorrect properties being set. Any ideas?
<?php
class User
{
private $username;
private $email
private $first_name;
private $last_name;
private $address;
private $address2;
function __construct()
{
}
function getUsername()
{
return $this->username
}
function setUsername($username)
{
$this->username = $username;
}
...
}
?>
Unless you are doing validation on the input, there's no point using getters/setters here in my opinion.
Make the properties public, and override the getters/setters for invalid properties using magic methods:
class User
{
public $username;
public $email;
public $first_name;
public $last_name;
public $address;
public $address2;
public function __get($var) {
throw new Exception("Invalid property $var");
}
public function __set($var, $value) {
$this->__get($var);
}
}
$user = new User;
$user->username = 'foo'; // works
$user->foo = 'bar'; // errors
First of all, can't you use public properties?
If no and your properties does not require any logic when getting/setting, i would use __get and __set.
If you really don't want "incorrect" properties being set (why?), a option could be to use a whitelist of properties that's okay to set:
function __set($key, $value) {
$whitelist = array("firstname", "lastname", ..);
if(!in_array($key, $whitelist))
throw new Exception("Invalid property");
}