DefaultPasswordHasher store password as plain text - cakephp

Am using cakephp 3 and i want to create login sistem on my app. I follow blog tutorial for auth. When i create new user password is stored as plain text, its not hashed. I dont know what do wrong. Check my code
I create table:
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
PASSWORD VARCHAR(255),
role VARCHAR(20),
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL
);
Also i create UsersTable and entity Users
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config
*/
public function initialize(array $config)
{
$this->table('users');
$this->primaryKey('id');
}
}
class User extends Entity
{
protected $_accessible = [
'username' => true,
'password' => true
];
protected function _setPassword($password) {
return (new DefaultPasswordHasher)->hash($password);
}
}
// App\Controller\AppController.php
$this->loadComponent('Auth', [
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'display',
'home'
]
]);
And inside UsersController i add:
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('add', 'logout');
}
// Login
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}
// Add
public function add() {
$user = $this->Users->newEntity($this->request->data);
if ($this->request->is('post')) {
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to add the user.'));
}
$this->set(compact('user'));
}

Related

Cannot instantiate abstract class Cake\Mailer\Mailer

I want to build forgot password page in cakephp
Here is my code of user controller
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Http\Exception\UnauthorizedException;
use Cake\Mailer\Email;
use Cake\Mailer\Mailer;
use Cake\email\TransportFactory;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Utility\Security;
use Cake\ORM\TableRegistry;
use Cake\Core\InstanceConfigTrait;
/**
Users Controller
#property \App\Model\Table\UsersTable $Users
#method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class UsersController extends AppController {
public function beforeFilter(\Cake\Event\Event $event) {
$this->Auth->allow([‘add’, ‘logout’]);
parent::beforeFilter($event);
}
/**
Index method
#return \Cake\Http\Response|null
*/
public function index() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException(__(‘You are not allowed to access this page’));
}
$users = $this->paginate($this->Users);
$this->set(compact(‘users’));
}
/**
View method
#param string|null $id User id.
#return \Cake\Http\Response|null
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null) {
$user = $this->Users->get($id, [
‘contain’ => [],
]);
$this->set(‘user’, $user);
}
/**
Add method
#return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->newEntity();
if ($this->request->is(‘post’)) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Edit method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->get($id, [
‘contain’ => [],
]);
if ($this->request->is([‘patch’, ‘post’, ‘put’])) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Delete method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects to index.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$this->request->allowMethod([‘post’, ‘delete’]);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success((‘The user has been deleted.’));
} else {
$this->Flash->error(__(‘The user could not be deleted. Please, try again.’));
}
return $this->redirect([‘action’ => ‘index’]);
}
public function forgotpassword()
{
if ($this->request->is(‘post’)) {
$email = $this->request->getData(‘email’);
$token = Security::hash(Security::randomBytes(25));
$userTable = TableRegistry::get(‘Users’);
if ($email == NULL) {
$this->Flash->error((‘Please insert your email address’));
}
if ($user = $userTable->find(‘all’)->where([‘email’=>$email])->first()) {
$user->token = $token;
if ($userTable->save($user)){
$mailer = new Mailer(‘default’);
$mailer->Transport(‘Smtp’);
$mailer->From([‘noreply[at]codethepixel.com’ => ‘myCake4’])
->setTo($email)
->setEmailFormat(‘html’)
->setSubject(‘Forgot Password Request’)
->deliver(‘Hello
Please click link below to reset your password
Reset Password’);
}
$this->Flash->success(‘Reset password link has been sent to your email (’.$email.’), please check your email’);
}
if ($total = $userTable->find(‘all’)->where([‘email’=>$email])->count()==0) {
$this->Flash->error((‘Email is not registered in system’));
}
}
}
public function resetpassword($token)
{
if($this->request->is(‘post’)){
$hasher = new DefaultPasswordHasher();
$newPass = $hasher->hash($this->request->getData(‘password’));
$userTable = TableRegistry::get(‘Users’);
$user = $userTable->find(‘all’)->where([‘token’=>$token])->first();
$user->password = $newPass;
if ($userTable->save($user)) {
$this->Flash->success(‘Password successfully reset. Please login using your new password’);
return $this->redirect([‘action’=>‘login’]);
}
}
}
public function login() {
if ($this->request->is(‘post’)) {
$user = $this->Auth->identify();
if ($user) {
if ($user[‘is_active’] === 1) {
$users = $this->Users->get($user[‘id’]);
$users->ip_address = $this->request->clientIp();
$users->last_login = date(‘Y-m-d h:i:s’);
if ($this->Users->save($users)) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error((‘Unable to login by your credentials.’));
}
} else {
$this->Flash->error((‘This user not activated, please contact our administrator.’));
}
}
$this->Flash->error(__(‘Invalid username or password, try again’));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
}
After opening forgot password page user enter their email following error received.
Cannot instantiate abstract class Cake\Mailer\Mailer
How do I solve this problem when the user entered their email & reset password will be sent to user's email which will be saved in our database.
Help me please #ndm
In your app.php
use Cake\Mailer\Transport\MailTransport;
.
.
.
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The following keys are used in SMTP transports:
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => null,
'password' => null,
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
'your_project' => [
'className' => 'Smtp',
'host' => 'your_host',
'port' => XXX,
'timeout' => 30,
'username' => 'your_email',
'password' => 'your_password',
'client' => null,
'tls' => true,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you#localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
'your_project' => [
'transport' => 'your_project',
'from' => ['your_email#teste.com' => 'My Site'],
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
Create a folder "Mailer" in src/Mailer. Create an UserMailer.php file
<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
class UserMailer extends Mailer
{
public static $name = 'User';
public function reset($user)
{
$this->to($user->email)
->profile('your_project')
->emailFormat('html')
->template('your_project', 'user')
->layout('user')
->viewVars(['name' => $user->name])
->subject(sprintf('Welcome...', $user->name))
->message("texte...");
}
}
In this case, I created a layout for my email. Create an "Email" folder in the layout.
On your controller, do the following:
$this->getMailer('User')->send('reset', [$user]);
Don't forget to import into the controller:
use Cake\Mailer\MailerAwareTrait;
I use it like this.
Go to the godaddy dashboard and find the SMTP information. It's all you need! Replace with your information

Cakephp 3.7.4 Auth hash password Not working

I am trying to implement auth login and register cakephp 3.7.4
I have used following code for UsersController add method
public function add()
{
$this->viewBuilder()->setLayout('login');
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$post = $this->request->getData();
$post['created'] = date('Y-m-d H:i:s');
$post['modified'] = date('Y-m-d H:i:s');
$user = $this->Users->patchEntity($user, $post);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'login']);
}
$this->Flash->error(__('Unable to add the user.'));
}
$this->set('user', $user);
}
But it can't save password in Hash Format
I have also create entity and used this function but it also not helped me
class User extends Entity
{
protected $_accessible = [
'email' => true,
'password' => true
];
protected $_hidden = [
'password'
];
protected function _setPassword($password){
return(new DefaultPasswordHasher)->hash($password);
}
}
I installed a fresh Cake 3.7.4 installation, baked a users table, users controller and users table/entity. The following code for the User Class successfully hashed the password before it is written to the database. Please compare it with your code.
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
class User extends Entity
{
protected $_accessible = [
'email' => true,
'password' => true,
'modified' => true,
'created' => true
];
protected $_hidden = [
'password'
];
protected function _setPassword($password)
{
return (new DefaultPasswordHasher())->hash($password);
}
}
Just use parenthesis around DefaultPasswordHaser():
return(new DefaultPasswordHasher())->hash($password);

CakePHP 3.0 - Login not working

I've been following the CakePHP 3.0 tutorials (Bookmarker & Blog) regarding the Login/Authentication sections and applying it to my own code, but I can't seem to get it working properly.
I'm able to see all indexes without even being logged in. Logging into the system does not work; the login page just refreshes.
EDIT: Okay, seems like my test users were duds, I made a new user and it can login. However, I still have the issue of non-users being able to see indexes of tables (they can't create any variables in any of the tables apart from User, which has been allowed specifically).
EDIT2: I fixed it by removing the beforeFilter function in AppController.
User Controller:
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
class UsersController extends AppController
{
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['add', 'logout']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Incorrect username or password, please try again.'));
}
}
public function logout()
{
$this->Flash->success('You are now logged out.');
return $this->redirect($this->Auth->logout());
}
public function index()
{
$this->set('users', $this->Users->find('all'));
}
public function view($id)
{
$user = $this->Users->get($id);
$this->set(compact('user'));
}
}
App Controller:
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
public function initialize()
{
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'display',
'home'
]
]);
}
}
User Table:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->requirePresence('username', 'create')
->notEmpty('username', 'A username is required');
$validator
->requirePresence('password', 'create')
->notEmpty('password', 'A password is required');
$validator
->email('email')
->requirePresence('email', 'create')
->notEmpty('email', 'An email is required');
$validator
->requirePresence('role', 'create')
->notEmpty('role', 'inList', [
'rule' => ['inList', ['admin', 'artist', 'engineer']],
'message' => 'Please enter a valid role'
]);
return $validator;
}
}
I managed to fix it by removing the beforeFilter function in AppController.
public function beforeSave(Event $event)
{
$entity = $event->data['entity'];
// Make a password for digest auth.
$entity->digest_hash = DigestAuthenticate::password(
$entity->username,
$entity->password,
env('SERVER_NAME')
);
return true;
}

cakephp3 restrict controller use depending on user type

I am using cakephp3. I have a simple web application that has users. I have two user types, Admin and Standard. I want to limit Standard user to only view and index data. Whereas Admin type user should be able to add, edit, delete, view and index user data.
Basically, I want to globally restrict standard users, so that they cannot access the add, edit and delete methods of the controller.
So can anyone help me achieve it?
Below is /src/Controller/UsersController.php
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* Users Controller
*
* #property \App\Model\Table\UsersTable $Users
*/
class UsersController extends AppController
{
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Countries', 'Cities', 'UserGroups', 'UserLevels']
];
$this->set('users', $this->paginate($this->Users));
$this->set('_serialize', ['users']);
}
public function dashboard()
{
}
/**
* View method
*
* #param string|null $id User id.
* #return void
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$user = $this->Users->get($id, [
'contain' => ['Countries', 'Cities', 'UserGroups', 'UserLevels', 'Alerts', 'DeviceLogs', 'Devices']
]);
$this->set('user', $user);
$this->set('_serialize', ['user']);
}
/**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$countries = $this->Users->Countries->find('list', ['limit' => 200]);
$cities = $this->Users->Cities->find('list', ['limit' => 200]);
$userGroups = $this->Users->UserGroups->find('list', ['limit' => 200]);
$userLevels = $this->Users->UserLevels->find('list', ['limit' => 200]);
$this->set(compact('user', 'countries', 'cities', 'userGroups', 'userLevels'));
$this->set('_serialize', ['user']);
}
/**
* Edit method
*
* #param string|null $id User id.
* #return void Redirects on successful edit, renders view otherwise.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$countries = $this->Users->Countries->find('list', ['limit' => 200]);
$cities = $this->Users->Cities->find('list', ['limit' => 200]);
$userGroups = $this->Users->UserGroups->find('list', ['limit' => 200]);
$userLevels = $this->Users->UserLevels->find('list', ['limit' => 200]);
$this->set(compact('user', 'countries', 'cities', 'userGroups', 'userLevels'));
$this->set('_serialize', ['user']);
}
/**
* Delete method
*
* #param string|null $id User id.
* #return \Cake\Network\Response|null Redirects to index.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success(__('The user has been deleted.'));
} else {
$this->Flash->error(__('The user could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error('Your username or password is incorrect.');
}
}
public function logout()
{
$this->Flash->success('You are now logged out.');
return $this->redirect($this->Auth->logout());
}
public function resetPassword() {
}
public function changepassword() {
}
}
Below is AppController.php
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
use \Crud\Controller\ControllerTrait;
public $components = [
'RequestHandler',
'Crud.Crud' => [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete'
],
'listeners' => [
'Crud.Api',
'Crud.ApiPagination',
'Crud.ApiQueryLog'
]
]
];
/**
* Initialization hook method.
*
* Use this method to add common initialization code like loading components.
*
* e.g. `$this->loadComponent('Security');`
*
* #return void
*/
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
// default is referer and in case of no referer loginRedirect (after login)
'loginRedirect' => [
'controller' => 'Users',
'action' => 'dashboard'
],
'logoutRedirect' => '/',
'authError' => "Y"
]);
// Allow the display action so our pages controller
// continues to work.
$this->Auth->allow(['resetPassword','add','changePassword','display']);
}
/**
* Before render callback.
*
* #param \Cake\Event\Event $event The beforeRender event.
* #return void
*/
public function beforeRender(Event $event)
{
if (!array_key_exists('_serialize', $this->viewVars) &&
in_array($this->response->type(), ['application/json', 'application/xml'])
) {
$this->set('_serialize', true);
}
}
}
Regards,
The right approach is to use ControllerAuthorize.
As described in the docs, you have to add in AppController the following:
public function isAuthorized($user = null)
{
// Any registered user can access public functions
if (empty($this->request->params['prefix'])) {
return true;
}
// Only admins can access admin functions
if ($this->request->params['prefix'] === 'admin') {
return (bool)($user['role'] === 'admin');
}
// Default deny
return false;
}
You then have to define admin as a valid key for prefix routing, and move your add, edit and delete actions to the new controller in
src/Controller/Admin/UsersController.php

cakephp auth component is not working

class UsersController extends AppController {
var $uses = array('User', 'Feed', 'Author', 'Comment', 'Tag', 'SingleArticle', 'Category');
var $helpers = array('Html', 'Form');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('signup');
}
public $components = array('Session', 'RequestHandler',
'Auth' => array(
'logoutRedirect' => array('controller' => 'users', 'action' => 'index'),
'authError' => "you can't access that page",
'authenticate' => array(
'Form' => array(// THIS IS WHERE YOU CHANGE THE DEFAULT FIELDS
'fields' => array('email' => 'email', 'pwd' => 'pwd'),
'passwordHasher' => 'Blowfish'
)
)
)
);
public function isAuthorized($user) {
return true;
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect(array('controller'=>'users','action'=>'mind'));
} else {
$this->Session->setFlash('login failed');
}
}
}
public function logout() {
$this->redirect($this->Auth->logout());
}
}
this is my userscontroller.php.
my appcontroller.php
public $components = array('Auth', 'RequestHandler');
public $pageTitle;
public function beforeFilter() {
$this->Auth->allow('index');
parent::beforeFilter();
}
my user.php
<?php
App::uses('AppModel', 'Model');
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public $name = 'User';
var $useTable = 'fvf_users';
public function beforeSave($options = array()) {
if (isset($this->data['User']['pwd'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data['User']['pwd'] = $passwordHasher->hash(
$this->data['User']['pwd']
);
}
return true;
}
}
please help me,my login page not worked.it will redirected to the same login page only.
i used the password hasing for blowfish method. please help me.thanks in advance.
which part is mistake in my code.what is the default password encryption method in cakephp.
Cakephp LOGIN not working...:(
Your fields array in config is incorrect. Assuming you db fields are email and pwd. The array needs to be 'fields' => array('username' => 'email', 'password' => 'pwd'). Your login form field names would also be email and pwd.

Resources