不区分大小写的身份验证 CakePHP 3

Case insensitive authentication CakePHP 3

我想让我的 CakePHP 应用程序的用户名检查不区分大小写。

目前我的 Auth 组件是这样加载的:

$this->loadComponent('Auth', [
    'loginAction' => [
        'controller' => 'Users',
        'action' => 'login'
    ],
    'authError' => 'You need to be logged in',
    'authenticate' => [
        'Form' => [
            'fields' => ['username' => 'username', 'password' => 'password'],
            'finder' => 'auth',
        ]
    ],
    'loginRedirect' => [
        'controller' => 'Pages',
        'action' => 'display',
        'home'
    ],
    'logoutRedirect' => [
        'controller' => 'login'
    ]
]);

我的 AuthFinder 看起来像这样:

/**
 * @param Query $query
 * @param array $options
 * @return Query
 */
public function findAuth(Query $query, array $options)
{
    return $query->contain(['Contacts'])
        ->where([
            'activated' => 'yes',
            'LOWER(username)' => strtolower($options['username'])
        ]);
}

但是尝试使用我的大写用户名登录不起作用。我该怎么做?

编辑 1:

这是在 Postgres 数据库上完成的。所以我没有 _ci 排序规则可供我使用

编辑 2:

这是对@dakota 评论的编辑:

/src/Model/Table/UsersTable.php (line 116)
object(Cake\ORM\Query) {

    '(help)' => 'This is a Query object, to get the results execute or iterate it.',
    'sql' => 'SELECT Users.id AS "Users__id", Users.contact_id AS "Users__contact_id", Users.username AS "Users__username", Users.password AS "Users__password", Users.last_login AS "Users__last_login", Users.last_login_ip AS "Users__last_login_ip", Users.password_reset_key AS "Users__password_reset_key", Users.password_reset_date AS "Users__password_reset_date", Users.is_super_user AS "Users__is_super_user", Users.configured AS "Users__configured", Users.activated AS "Users__activated", Contacts.id AS "Contacts__id", Contacts.firstname AS "Contacts__firstname", Contacts.lastname AS "Contacts__lastname", Contacts.id_number AS "Contacts__id_number", Contacts.company_id AS "Contacts__company_id", Contacts.has_own_transport AS "Contacts__has_own_transport", Contacts.vehicle_license_type AS "Contacts__vehicle_license_type", Contacts.max_travel_distance AS "Contacts__max_travel_distance", Contacts.description AS "Contacts__description", Contacts.first_language AS "Contacts__first_language", Contacts.second_language AS "Contacts__second_language", Contacts.facebook AS "Contacts__facebook", Contacts.twitter AS "Contacts__twitter", Contacts.linkedin AS "Contacts__linkedin", Contacts.profile_image AS "Contacts__profile_image", Contacts.cell_number AS "Contacts__cell_number", Contacts.date_of_birth AS "Contacts__date_of_birth", Contacts.gender AS "Contacts__gender", Contacts.address AS "Contacts__address", Contacts.coordinates AS "Contacts__coordinates", Contacts.is_agent AS "Contacts__is_agent", Contacts.rate AS "Contacts__rate" FROM users Users INNER JOIN contacts Contacts ON Users.id = (Contacts.id) WHERE (Users.username = :c0 AND activated = :c1 AND LOWER(username) = :c2)',
    'params' => [
        ':c0' => [
            'value' => 'myemail@domain.com',
            'type' => 'string',
            'placeholder' => 'c0'
        ],
        ':c1' => [
            'value' => 'yes',
            'type' => 'string',
            'placeholder' => 'c1'
        ],
        ':c2' => [
            'value' => 'myemail@domain.com',
            'type' => null,
            'placeholder' => 'c2'
        ]
    ],
    'defaultTypes' => [
        'Users__id' => 'integer',
        'Users.id' => 'integer',
        'id' => 'integer',
        'Users__contact_id' => 'integer',
        'Users.contact_id' => 'integer',
        'contact_id' => 'integer',
        'Users__username' => 'string',
        'Users.username' => 'string',
        'username' => 'string',
        'Users__password' => 'string',
        'Users.password' => 'string',
        'password' => 'string',
        'Users__last_login' => 'timestamp',
        'Users.last_login' => 'timestamp',
        'last_login' => 'timestamp',
        'Users__last_login_ip' => 'string',
        'Users.last_login_ip' => 'string',
        'last_login_ip' => 'string',
        'Users__password_reset_key' => 'string',
        'Users.password_reset_key' => 'string',
        'password_reset_key' => 'string',
        'Users__password_reset_date' => 'timestamp',
        'Users.password_reset_date' => 'timestamp',
        'password_reset_date' => 'timestamp',
        'Users__is_super_user' => 'string',
        'Users.is_super_user' => 'string',
        'is_super_user' => 'string',
        'Users__configured' => 'string',
        'Users.configured' => 'string',
        'configured' => 'string',
        'Users__activated' => 'string',
        'Users.activated' => 'string',
        'activated' => 'string',
        'Contacts__id' => 'integer',
        'Contacts.id' => 'integer',
        'Contacts__firstname' => 'string',
        'Contacts.firstname' => 'string',
        'firstname' => 'string',
        'Contacts__lastname' => 'string',
        'Contacts.lastname' => 'string',
        'lastname' => 'string',
        'Contacts__id_number' => 'string',
        'Contacts.id_number' => 'string',
        'id_number' => 'string',
        'Contacts__company_id' => 'string',
        'Contacts.company_id' => 'string',
        'company_id' => 'string',
        'Contacts__has_own_transport' => 'string',
        'Contacts.has_own_transport' => 'string',
        'has_own_transport' => 'string',
        'Contacts__vehicle_license_type' => 'string',
        'Contacts.vehicle_license_type' => 'string',
        'vehicle_license_type' => 'string',
        'Contacts__max_travel_distance' => 'string',
        'Contacts.max_travel_distance' => 'string',
        'max_travel_distance' => 'string',
        'Contacts__description' => 'text',
        'Contacts.description' => 'text',
        'description' => 'text',
        'Contacts__first_language' => 'integer',
        'Contacts.first_language' => 'integer',
        'first_language' => 'integer',
        'Contacts__second_language' => 'integer',
        'Contacts.second_language' => 'integer',
        'second_language' => 'integer',
        'Contacts__facebook' => 'string',
        'Contacts.facebook' => 'string',
        'facebook' => 'string',
        'Contacts__twitter' => 'string',
        'Contacts.twitter' => 'string',
        'twitter' => 'string',
        'Contacts__linkedin' => 'string',
        'Contacts.linkedin' => 'string',
        'linkedin' => 'string',
        'Contacts__profile_image' => 'string',
        'Contacts.profile_image' => 'string',
        'profile_image' => 'string',
        'Contacts__cell_number' => 'string',
        'Contacts.cell_number' => 'string',
        'cell_number' => 'string',
        'Contacts__date_of_birth' => 'date',
        'Contacts.date_of_birth' => 'date',
        'date_of_birth' => 'date',
        'Contacts__gender' => 'string',
        'Contacts.gender' => 'string',
        'gender' => 'string',
        'Contacts__address' => 'string',
        'Contacts.address' => 'string',
        'address' => 'string',
        'Contacts__coordinates' => 'string',
        'Contacts.coordinates' => 'string',
        'coordinates' => 'string',
        'Contacts__is_agent' => 'string',
        'Contacts.is_agent' => 'string',
        'is_agent' => 'string',
        'Contacts__rate' => 'decimal',
        'Contacts.rate' => 'decimal',
        'rate' => 'decimal'
    ],
    'decorators' => (int) 0,
    'executed' => false,
    'hydrate' => true,
    'buffered' => true,
    'formatters' => (int) 0,
    'mapReducers' => (int) 0,
    'contain' => [
        'Contacts' => []
    ],
    'matching' => [],
    'extraOptions' => [
        'username' => 'myemail@domain.com'
    ],
    'repository' => object(App\Model\Table\UsersTable) {

        'registryAlias' => 'Users',
        'table' => 'users',
        'alias' => 'Users',
        'entityClass' => 'App\Model\Entity\User',
        'associations' => [
            (int) 0 => 'contacts',
            (int) 1 => 'users'
        ],
        'behaviors' => [],
        'defaultConnection' => 'default',
        'connectionName' => 'default'

    }

}

如果您查看查询的最后,您会发现它有:

WHERE (Users.username = :c0 AND activated = :c1 AND LOWER(username) = :c2)

您提供的条件只是后两个; Cake 会自动为您放置第一个。您显然不希望这样,但是您应该能够使用 where 函数的第三个参数来替换所有条件:

return $query->contain(['Contacts'])
    ->where([
        'activated' => 'yes',
        'LOWER(username)' => strtolower($options['username'])
    ], [], true);