如何在PHP中防止相同(敏感时为大写/小写)用户名?

如何在PHP中防止相同(敏感时为大写/小写)用户名?,php,Php,我可以防止多个用户使用相同的用户名注册,代码如下: $sqlusercheck = "SELECT (SELECT COUNT(row_username) FROM table_users WHERE row_username = :username LIMIT 1) as checkusername"; $stmt = $database->prepare($sqlusercheck); $stmt->bindValue(':username', $username); $stmt

我可以防止多个用户使用相同的用户名注册,代码如下:

$sqlusercheck = "SELECT (SELECT COUNT(row_username) FROM table_users WHERE row_username = :username LIMIT 1) as checkusername";
$stmt = $database->prepare($sqlusercheck);
$stmt->bindValue(':username', $username);
$stmt->execute();
$row = $stmt->fetch();

if ($row->checkusername > 0) {
    $this->error[] = "This username is already taken.";
    $success = false;
}
因此,如果数据库中有
Abc
,用户不能使用用户名
Abc
,但他无论如何可以注册
Abc
Abc
Abc
,等等,这是我想要阻止的

作为一个可能的解决方案,我不想
strtolower()
username。相反,我希望
Abc
用户使用他的密码登录,无论他是否编写登录输入
Abc
Abc
Abc
,等等

我为什么要这个

我观察到,用户可以在其计算机上使用用户名
abc
注册。但当他想登录他的移动设备时,设备会自动大写第一个字母,用户无法登录。反之亦然

那么,为什么我不想要strtolower()

因为也有用户希望显示为abC
abC
,并有意这样注册自己。因此,他们的用户名将在注册时显示。

在查询中使用mysql,并在绑定参数时使用PHP函数:-

$sqlusercheck = "SELECT (SELECT COUNT(row_username) FROM table_users WHERE LOWER(row_username) = :username LIMIT 1) as checkusername";
$stmt = $database->prepare($sqlusercheck);
$stmt->bindValue(':username', strtolower($username)); // use strtolower function
$stmt->execute();
$row = $stmt->fetch();

希望它能帮助您:)

在这种情况下,您可以受益于mysql的
LOWER()
和php的
strtolower()
函数。(不要担心,只有在您检查可用性时才可以。)

如果您这样更改查询,它将使这两个值都小写,并比较它们是否相同

如果是,将显示您的错误

如果不是,它将按照用户键入的方式添加到数据库中


注意:对于您描述的登录,您应该对登录查询进行相同的更改。

您可以尝试以下解决方案:

$sqlusercheck = "SELECT (SELECT COUNT(row_username) FROM table_users WHERE LOWER(row_username) = :username LIMIT 1) as checkusername";
$stmt = $database->prepare($sqlusercheck);
$stmt->bindValue(':username', strtolower($username));
$stmt->execute();
$row = $stmt->fetch();

if ($row->checkusername > 0) {
    $this->error[] = "This username is already taken.";
    $success = false;
}
MySQL 这取决于您的表格排序。如果它以
\u ci
结尾,则在执行非二进制字符串比较时,它已经不区分大小写,默认情况下,它们已经是。但是,如果它以
\u cs
\u bin
结尾,则它区分大小写

如果表排序规则区分大小写,并且希望执行不区分大小写的查询,则可以向查询中添加
COLLATE
,如下所示:

... WHERE row_username COLLATE collation_you_want_ci = :username LIMIT 1
如果要对
\u ci
排序规则执行区分大小写的查询,而不必将字符串转换为大写或小写,可以使用:

PostgreSQL
在PostgreSQL中,字符串比较的默认值区分大小写。您可以使用
ILIKE
~*
LOWER
,但请注意,这些都可能会影响索引的性能。使用数据类型或基于函数的索引。

首先转换小写字母的输入,然后获取数据并转换为小写字母,然后匹配(如果相等)。存储用户输入的注册用户名,但确保任何DB或PHP操作执行
strtolower()
strtolower()
(或DB等效项)在评估任何比较之前。仅在数据库中执行-排序:
utf\u 8\u general\u ci
,使用
UNIQUE
键。无论如何,您都做错了。您应该使列在数据库中唯一。那你根本不需要做这个检查。只要尝试插入并在失败时显示相应的消息即可。按自己的方式操作容易出现计时窗口错误。除了@EJP所说的之外,在尝试插入之前检查存在性有点反模式/可能会造成竞争条件:在检查存在性和尝试插入该记录之间,可能已被占用,这使得您的检查无效。如果您只是尝试插入,则不会出现问题,因为操作是原子的(好吧,取决于您的数据库)。另外值得注意的是,默认情况下MySQL(OP未提及,但很流行)使用不区分大小写的排序规则。@RobFarr您是对的;非常感谢。我已经更新了我的答案。1)您缺少一个
用于
bindValue
。2) 这很容易出现错误:两个用户可能同时尝试注册为
abc
abc
sqlusercheck
可能会说用户名没有问题,因为不存在其他用户,然后您会同时使用您不允许的用户名注册两个用户。
... WHERE row_username COLLATE collation_you_want_ci = :username LIMIT 1
... WHERE BINARY row_username = :username LIMIT 1