【问题标题】:Pass extra data to finder auth将额外数据传递给 finder auth
【发布时间】:2015-10-22 02:28:07
【问题描述】:

我来自Auth 的查找器具有我需要访问$this->request 的条件,但我无法访问UsersTable

AppController::初始化

$this->loadComponent('Auth', [
        'authenticate' => [
            'Form' => [
                'finder' => 'auth',
            ]
        ]
    ]);

用户表

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;
}

我需要将额外数据从AppController 传递到finder auth,因为我无法访问UsersTable 上的$this->request->data

更新

人们在 cmets 上说这是一个糟糕的设计,所以我将准确解释我需要什么。

我有一个表users,但每个用户都属于一个gymusername(email) 仅对特定的gym 是唯一的,因此我可以从gym_id 1 获得一个example@domain.com,从gym_id 2 获得另一个example@domain.com。 在登录页面我有gym_slug 告诉auth finder 我提供的用户gym 属于哪个username

【问题讨论】:

  • 这对我来说听起来可能是糟糕的设计,你能展示你想要传递的东西吗?但是,它必须以某种方式作为一种行为是可能的:-)
  • 我在 url 传递了一个健身房 slug,所以我需要根据那个 slug 获取健身房的 ID,以便在用户查找时进行过滤,因为我在 users 表中有 gym_id。我可以通过this->request->params['gym_slug] 访问slug,但我在UsersTable 没有访问权限
  • 我们需要更多信息才能继续。从问题和 cmets 看来,您可能正在对用户进行身份验证,然后试图将他们重定向到他们的健身房页面?编辑您的问题并准确提供您在做什么以及为什么。在上面的评论之前你没有提到健身房,我很好奇为什么你需要重定向请求数据(如果这就是你正在做的事情的话),因为你将gym_id 存储在同一个表中。
  • 我从来没有提到过redirect 我只需要finder 上的gym_slugwhere 上用作condition,就这么简单。我将编辑和解释更多。

标签: authentication orm cakephp-3.0


【解决方案1】:

据我所知,没有办法通过将其传递到 3.1 中的配置来做到这一点。这可能是一个好主意,在 cakephp git hub 上作为功能请求提交。

有一些方法可以通过创建一个新的身份验证对象来扩展基本身份验证,然后覆盖 _findUser 和 _query。像这样的:

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;
 }
 }

欲了解更多信息,请参阅:Creating Custom Authentication Objects

【讨论】:

  • 对我有用,可惜我不能在它到期之前给你赏金
  • 没关系!任何可以帮助开发人员的事情!
【解决方案2】:

我知道这是一个老问题,但我想我会将我正在使用的查找器发布在我们基于 Cakephp 3 构建的 SaaS 应用程序之一中。它是否遵循 DRY 等可能不遵循。要说一切都可以通过 X 或 Y 方式完成......你总是不得不改变规则。在这种情况下,取决于 URL(xdomain.com 或 ydomain.com),我们的应用程序会确定客户是谁并更改布局等。此外,基于用户的用户与电子邮件和 site_id 非常相似

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;
}

希望对大家有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    • 2018-10-07
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 2021-02-27
    相关资源
    最近更新 更多