Need help because i'm still new to Yii2. I want to encrypt the password before saving it to the database. So i'm using sha1 but the problem is that the password field in the form has contents when i apply this line of code in the controller shown below.
$model->password = sha1($model->attributes['password']);
This is the Controller create method:
public function actionCreate()
{
$model = new Employeeinformation();
//$model->password = sha1($model->attributes['password']);
$model->created_date = date('Y-m-d H:i:s');
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->employee_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
This is the form:
<div class="employeeinformation-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'employee_id')->textInput(['minlength' => true, 'maxlength' => true]) ?>
<?= $form->field($model, 'password')->passwordInput(['maxlength' => true]) ?>
<?= $form->field($model, 'last_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'first_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'hired_date')->widget(\yii\jui\DatePicker::classname(), [
'language' => 'en',
'dateFormat' => 'yyyy-MM-dd',
]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Screenshot of my problem:
http://i.imgur.com/YTDW1Ud.png
Thank you in advance.
I want to encrypt the password before saving it to the database.
No you don't. Well, you might think you want to encrypt the password, but if you're trying to protect users you actually want to hash the password, not encrypt it.
SHA1 doesn't provide encryption, it's a hash function. This is a very common misconception. You can learn more about basic cryptography terms and concepts at the linked blog post.
More importantly: You don't want a fast hash like SHA1 for passwords. Use password_hash() and password_verify() and you'll have secure password storage. You don't even need to particularly care what these functions do internally to use them correctly.
public function actionCreate()
{
$model = new Employeeinformation();
$post = Yii::$app->request->post();
if ($model->load($post)) {
$model->password = password_hash($model->password, PASSWORD_DEFAULT);
$model->created_date = date('Y-m-d H:i:s');
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->employee_id]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
When employees login, you just need to do this:
if (password_verify($request->password, $storedEmployeeData->hashed_password)) {
// Success
}
Yii2 comes with user module in advanced setup. See how it store user passwords in encrypted way.
You can use setPassword() method in User Model to get hashed passwords.
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
and call this method before saving model data.
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
if ($user->save()) {
return $user;
}
}
return null;
}
Also look at the Yii2 doc for passwords and authentication.
The content for password is there because you set the attribute before sending the data through the save (and validate) method.
If you like to do it in the controller, you can do it as the following:
public function actionCreate()
{
$model = new Employeeinformation();
if ($model->load(Yii::$app->request->post())){
$model->password = sha1($model->password);
$model->created_date = date('Y-m-d H:i:s');
if ($model->save())
return $this->redirect(['view', 'id' => $model->employee_id]);
}
return $this->render('create', [
'model' => $model,
]);
}
Another way, is to do the password hashing in the beforeSave method of the Employeeinformation model (add this method inside the model class):
public function beforeSave($insert)
{
if(isset($this->password))
$model->password = sha1($model->password);
$model->created_date = date('Y-m-d H:i:s');
return parent::beforeSave($insert);
}
If done using the beforeSave method, these two lines in the controller code can be removed as they are no longer necessary:
$model->password = sha1($model->password);
$model->created_date = date('Y-m-d H:i:s');
However, referring to http://www.yiiframework.com/doc-2.0/guide-security-passwords.html, it is not recommended to use md5 or sha1 for password encryption. Yii2 provide two helper functions to generate & verify password.
Use this to encrypt password:
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);
And to verify it:
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
// all good, logging user in
} else {
// wrong password
}
This is a better choice than sha1 that is used in the original code you posted.
you can look at User model for example, there are method setPassword()
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
this is how to you set password on database, and also it's already encrypt by yii2 encription
$password = md5($password);
Best way to handle, make sure to correlate this to the login screen to check
$passwordentered = md5($passwordentered);
if ($passwordentered = "Correct"){
"Grant Access"
}
Hope this helps.
In your model add:
public function beforeSave()
{
$this->password=md5($this->password);
return true;
}
Now add this to your controller:
$model->password = md5($model->password);
Related
I am trying to generate unique usernames for users upon registration using laravel. I want to include both the first name and the last name. If I use only the first or last name it works, but if I try both, it enters a blank value to the database. Please Help.
Here is my code:
Auth Controller
`
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'firstname'=>'required|max:191',
'lastname'=>'required|max:191',
'phone'=>'required',
'email'=>'required|email|max:191|unique:users,email',
'password'=>'required|min:6',
]);
if($validator->fails())
{
return response()->json([
'validation_errors'=>$validator->messages(),
]);
}
else
{
$userObject = New User;
$userName = $userObject->generateUserName($request['firstname'.'lastname']);
$user = User::create([
'firstname'=>$request->firstname,
'lastname'=>$request->lastname,
'phone'=>$request->phone,
'email'=>$request->email,
'password'=>Hash::make($request->password),
'username'=>$userName,
]);
$token = $user->createToken($user->phone.'_Token')->plainTextToken;
return response()->json([
'status'=>200,
'username'=>$user->firstname,
'token'=>$token,
'message'=>'Registered Successfully',
]);
}
}
`
The User Model
`
public function generateUserName($firstname){
$username = Str::lower(Str::slug($firstname));
if(User::where('username', '=', $username)->exists()){
$uniqueUserName = $username.'-'.Str::lower(Str::random(5));
$username = $this->generateUserName($uniqueUserName);
}
return $username;
}
`
your issue generate from $request['firstname'.'lastname'], you are actually Concating keys of a request array though you want to Concat the value of 2 separate keys which means to use it like this $request['firstname'] and $request['lastname']. please change the below line
$userName = $userObject->generateUserName($request['firstname'.'lastname']);
with this
$userName = $userObject->generateUserName($request['firstname'].$request['lastname']);
I have one form that form have below fields
i)Book
ii)Amount
Controller action:
public function actionBook()
{
$model = new Book();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
$model->getBook();
return $this->render('BookForm', ['model' => $model]);
}
Whenever this page will load i will call one model function by default, the function is getBook()
Model:
public book;
public amount;
public showAmountField;
public function rules()
{
return [
[['book'], 'required'],
['amount', 'required', 'when' => function($model) {
return $model->showAmountField == true;
}],
];
}
public function getBook()
{
if(some condition here){
$this->showAmountField = true;
}
}
so whenever the showAmountField is true at the time the amount field is required, otherwise it will not required, here all are working fine and the client side validation also working fine, but when i change amount field id using console(f12) at the time the server side validation not working and form is simply submit with the amount field is empty, so what is wrong here. Please explain anyone.
UPDATE
View
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->params['breadcrumb'] = $model->breadCrumbs;
?>
<?php $form = ActiveForm::begin([
'id' => 'book-form',
'options' => ['class' => 'form-horizontal'],
]);
?>
<?= $form->field($model, 'book')->textInput()->label("Book"); ?>
<?php if($model->showAmountField): ?>
<?= $form->field($model, 'amount')->textInput()->label("Amount"); ?>
<?php endif; ?>
<?= $form->errorSummary($model, ['header' => '']); ?>
<?php ActiveForm::end(); ?>
Validation occurs on the field ID, if you change it through the console, the model does not understand that it needs to validate
$model = new Book();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
$model->getBook();
here you are initialising the $model->getBook(); after the if block so the model gets overridden in post request with new instance and hence server side validations fails for when condition.
$model = new Book();
$model->getBook();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
it should be before post load
I'm trying to implement a forgot password function in CakePHP 3.x.
I have created a form that accepts a user's email:
<?= $this->Form->create()?>
<div class="form-group">
<?= $this->Form->input('email', array('class' => 'form-group','autocomplete' => 'off' ,'required' => 'required'))?>
</div>
<div class="form-group">
<?= $this->Form->button('Reset Password', array('class' => 'form-group primary'))?>
</div>
<?= $this->Form->end()?>
In my controller I'm trying to find the user by the email, if the email exist then a random password will be generated and the password will be updated for that email id:
use Cake\ORM\TableRegistry;
use Cake\Auth\DefaultPasswordHasher;
public function forgotPassword($email = null){
if($this->request->is('post')) {
$email = $this->request->data['email'];
$emails = TableRegistry::get('Users');
$user = $emails->find()->where(['email' => $email ])->first();
if (!$user) {
$this->Flash->error(__('No user with that email found.'));
return $this->redirect(['controller' => 'Users','action' => 'forgotPassword']);
}else{
$random = 'a';
$hasher = new DefaultPasswordHasher();
$val = $hasher->hash($random);
$data = $this->Users->password = $val;
if ($this->Users->save($data)) {
$this->Flash->success(__('Password changed Succesfully.'));
return $this->redirect(['controller' => 'Users','action' => 'forgotPassword']);
}
}
}
}
You haven't actually stated a specific problem/question, but I think I might know what could help.
The whole DefaultPasswordHasher bit should be in the UsersEntity file, like in the tutorial: Blog tutorial
With the hashing properly placed in the entity like in the example it will automatically be called as soon as you use either PatchEntity or NewEntity (I think, confirmation please?).
Secondly, the $this->[model]->save() function works on entities, not just on data. So you would find the user's entity, patch the entity and then save it:
...} else {
$newpass = 'randomstring';
$user = $this->Users->PatchEntity($user, ['password' => $newpass]);
if ($this->Users->save($user)) ...
I am trying to display the details like username and email of the user who logged in to their account. I am using default login of yii framework and I have profile table which authenticates the user. In fact I am trying to pass the username of the user as the parameters. This is the login action which checks for username and password.
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->redirect(Yii::$app->request->baseUrl.'/todo/index');
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login() )
{
return $this->redirect(Yii::$app->request->baseUrl.'/todo/index/<?php echo $model->username;?>'); //this is how i like to pass the username as parameter
}
return $this->render('login', [
'model' => $model,
]);
}
In Default LoginFrom Model data is under getUser function
So final code will be:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->redirect(Yii::$app->request->baseUrl.'/todo/index');
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login() )
{
return $this->redirect(Yii::$app->request->baseUrl.'/todo/index/' . $model->getUser()->username); //this is how i like to pass the username as parameter
}
return $this->render('login', [
'model' => $model,
]);
}
I've made a few apps with Yii2, but having some trouble with the login functionality here. The passwords don't seem to match.
_form.php
<?= $form->field($model, 'first_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'last_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'email')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'pass')->passwordInput(['maxlength' => true]) ?>
User.php
public function beforeSave($insert)
{
if($this->isNewRecord)
{
$this->pass = Yii::$app->getSecurity()->generatePasswordHash($this->pass);
}
return parent::beforeSave($insert);
}
LoginForm.php
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
echo 'current: ' . $user->pass;
echo '<br />';
echo 'plain: ' . Yii::$app->getSecurity()->generatePasswordHash('Password');
echo '<br />';
echo 'function: ' . $user->validatePassword($this->pass);
if (!$user || !$user->validatePassword($this->pass)) {
$this->addError($attribute, 'Incorrect user or password.');
}
}
}
My email and password fail here. I echoed out some things to check. The user value from the DB is always the same, the plain version where I pass "Password" always returns a different hash and the third print_r() returns nothing. I'm not sure what I'm doing wrong here?
Check this code:
$password = 'Password';
$passwordHash = Yii::$app->getSecurity()->generatePasswordHash($password);
Yii::$app->getSecurity()->validatePassword($password, $passwordHash);
You should:
Correct write result of generatePasswordHash to database
use that hash on validatePassword method
Write correct user->validatePassword method like this:
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
the generatePasswordHash function will always create different value if you do print_r().
but the validatePassword function always return true if your password string is correct
so never mind about it.
maybe your column length in database is to short to save the hash