如何确保Symfony UserBadge始终支持不区分大小写的用户名校验
实现跨数据库保持用户名不区分大小写查询的两种主流方案
方案1:存储层统一格式化(推荐)
- 注册/保存用户信息时,统一将用户名/邮箱字段转为全小写(或全大写)后入库,确保存储的用户标识格式统一
- 认证阶段获取到用户传入的标识后,先做相同的大小写转换,再传给
UserBadge即可
示例代码:
// 认证逻辑中先做转换 $userIdentifier = strtolower($this->getUserIdentifierFromRequest()); return new Passport( new UserBadge($userIdentifier), // 其余逻辑不变 );
该方案性能最优,不需要修改查询逻辑,也不会出现数据库函数导致索引失效的问题,兼容性最好。
方案2:自定义用户提供器,查询时统一格式化
如果不想修改原有存储逻辑,可以自定义实现UserProviderInterface替换默认的EntityUserProvider,在查询时统一对字段和传入值做大小写转换后比对:
// 自定义UserProvider中的查询逻辑 public function loadUserByIdentifier(string $identifier): UserInterface { $user = $this->em->getRepository(User::class) ->createQueryBuilder('u') // 用SQL的LOWER函数统一转小写比对 ->where('LOWER(u.email) = :inputIdentifier') ->setParameter('inputIdentifier', strtolower($identifier)) ->getQuery() ->getOneOrNullResult(); if (null === $user) { throw new UserNotFoundException(); } return $user; }
完成后需要在config/packages/security.yaml中配置使用该自定义用户提供器即可。
如果后续需要改成区分大小写的查询,只要移除上述的大小写转换逻辑,同时如果使用的是默认不区分大小写的数据库,在查询时添加对应数据库的二进制比对规则即可,比如MariaDB/MySQL可以在查询条件中加入BINARY关键字,PostgreSQL等原生区分大小写的数据库直接使用等值查询即可。
内容的提问来源于stack exchange,提问作者Andrei Herford
相关产品推荐
相关产品推荐

