问题
My finder from Auth
has conditions that I need to access $this->request
but I don't have access for that on UsersTable
.
AppController::initialize
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'finder' => 'auth',
]
]
]);
UsersTable
public function findAuth(Query $query, array $options)
{
$query
->select([
'Users.id',
'Users.name',
'Users.username',
'Users.password',
])
->where(['Users.is_active' => true]); // If i had access to extra data passed I would use here.
return $query;
}
I need pass an extra data fom AppController
to finder
auth
since I dont have acces to $this->request->data
on UsersTable
.
Update
People are saying on comments that is a bad design so I will explain exactly what I need.
I have a table users
but each user belongs to a gym
.
The username(email)
is unique only to a particular gym
so I can have a example@domain.com
from gym_id 1
and another example@domain.com
from gym_id 2
.
On login page I have the gym_slug
to tell to auth finder
wich gym
the user username
that I provied belongs.
回答1:
To my knowledge, there is no way to do this by passing it into the configuration in 3.1. This might be a good idea submit on the cakephp git hub as a feature request.
There are ways to do it by creating a new authentication object that extends base authenticate and then override _findUser and _query. Something like this:
class GymFormAuthenticate extends BaseAuthenticate
{
/**
* Checks the fields to ensure they are supplied.
*
* @param \Cake\Network\Request $request The request that contains login information.
* @param array $fields The fields to be checked.
* @return bool False if the fields have not been supplied. True if they exist.
*/
protected function _checkFields(Request $request, array $fields)
{
foreach ([$fields['username'], $fields['password'], $fields['gym']] as $field) {
$value = $request->data($field);
if (empty($value) || !is_string($value)) {
return false;
}
}
return true;
}
/**
* Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields`
* to find POST data that is used to find a matching record in the `config.userModel`. Will return false if
* there is no post data, either username or password is missing, or if the scope conditions have not been met.
*
* @param \Cake\Network\Request $request The request that contains login information.
* @param \Cake\Network\Response $response Unused response object.
* @return mixed False on login failure. An array of User data on success.
*/
public function authenticate(Request $request, Response $response)
{
$fields = $this->_config['fields'];
if (!$this->_checkFields($request, $fields)) {
return false;
}
return $this->_findUser(
$request->data[$fields['username']],
$request->data[$fields['password']],
$request->data[$fields['gym']],
);
}
/**
* Find a user record using the username,password,gym provided.
*
* Input passwords will be hashed even when a user doesn't exist. This
* helps mitigate timing attacks that are attempting to find valid usernames.
*
* @param string $username The username/identifier.
* @param string|null $password The password, if not provided password checking is skipped
* and result of find is returned.
* @return bool|array Either false on failure, or an array of user data.
*/
protected function _findUser($username, $password = null, $gym = null)
{
$result = $this->_query($username, $gym)->first();
if (empty($result)) {
return false;
}
if ($password !== null) {
$hasher = $this->passwordHasher();
$hashedPassword = $result->get($this->_config['fields']['password']);
if (!$hasher->check($password, $hashedPassword)) {
return false;
}
$this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
$result->unsetProperty($this->_config['fields']['password']);
}
return $result->toArray();
}
/**
* Get query object for fetching user from database.
*
* @param string $username The username/identifier.
* @return \Cake\ORM\Query
*/
protected function _query($username, $gym)
{
$config = $this->_config;
$table = TableRegistryget($config['userModel']);
$options = [
'conditions' => [$table->aliasField($config['fields']['username']) => $username, 'gym' => $gym]
];
if (!empty($config['scope'])) {
$options['conditions'] = array_merge($options['conditions'], $config['scope']);
}
if (!empty($config['contain'])) {
$options['contain'] = $config['contain'];
}
$query = $table->find($config['finder'], $options);
return $query;
}
}
For more information see this: Creating Custom Authentication Objects
回答2:
I know this is an old question but I thought I would post the finder I am using in one of our SaaS apps built on Cakephp 3. Does it follow DRY etc probably not. To say everything can be done X or Y way ..... you always have to bend the rules. In this case depending on the URL (xdomain.com or ydomain.com) our app figures out who the customer is and changes layouts etc. Also the user based is tied to Email & site_id much like yours
public function findAuth(\Cake\ORM\Query $query, array $options) {
$query
->select([
'Users.id',
'Users.email',
'Users.password',
'Users.site_id',
'Users.firstname',
'Users.lastname'])
->where([
'Users.active' => 1,
'Users.site_id'=> \Cake\Core\Configure::read('site_id')
]);
return $query;
}
Anyway hope it helps someone
来源:https://stackoverflow.com/questions/33272426/pass-extra-data-to-finder-auth