当前位置: 首页 > 面试题库 >

Django:身份验证用户名是否区分大小写?

周高畅
2023-03-14
问题内容

Django默认情况下将用户名区分大小写,现在为了进行身份验证,我编写了自己的Authentication Backend用户名以在身份验证时处理不区分大小写的用户名。

如所示:http :
//blog.shopfiber.com/?p=220

现在,问题是:

我有各种观点和util方法,与之相比username有些刺痛。

request.user.username == username_from_some_other_system_as_str

现在,如果用户名是yugal

request.user.username == 'Yugal' # Returns False

现在,它应该返回True[我想要实现的目标]

为此,我记得C++几天Operator Overloading。但是我认为,对于djangoauth user来说,这样做并不是一个好主意,因为auth user它与紧密相关django。同样,重载==将使其对整个类(不只是对username字段)不区分大小写。

因此,username即使进行整体比较,我也应该如何处理这种不区分大小写的问题。

注意:

  • get_username始终无法创建一种返回小写用户名的方法,因为它将需要重构所有代码才能使用它。您可以一次为您的代码执行此操作,但是如果您使用的是第三方django应用程序,则无法执行此操作。

  • 我知道这user.username.lower() = something.lower()是可能的,但是容易出错,而不是针对多开发人员设置中经常使用的某些东西的写解决方案。

  • 我已SomeModel.objects.filter(username__iexact=username)尽可能使用过。但这仍然使系统容易受到任何不了解的开发人员的错误的影响。

=====================================

从概念上找出解决方案,但无法使其工作(帮助):

####### Custom CharField for username case-insensitivity #######
from django.db.models.fields import CharField
class iUnicode:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        if isinstance(other, str) or isinstance(other, unicode):
            return self.value.lower() == other.lower()
        if isinstance(other, self.__class__):
            return other == self.value

    def __unicode__(self):
        return unicode(self.value)
    def __str__(self):
        return self.__unicode__()


class UsernameCharField(CharField):
    def to_python(self, value):  # Its not getting called
        unicode_val = super(CharField, self).to_python(value)
        return iUnicode(unicode_val)

if User._meta.local_fields[1].name == 'username':
    User._meta.local_fields[1] = UsernameCharField(max_length=30)
    User._meta.local_fields[1].model = User
################################################################

我假设to_python用于将从数据库接收的值转换为unicodepython中的值。但是,我想我to_python没有接到电话。

这也将确保第三方应用程序不区分大小写,并且不需要任何重构。它将修补User其核心。我将添加到__init__.py我的第一个INSTALLED_APP

我究竟做错了什么 ?


问题答案:

终于明白了:

经过大量的实验和对User模型的最小影响,终于实现了它。[感谢 @freakish先生 的不同想法]

这里是 :

############ username case-insensitivity ############
class iunicode(unicode):
    def __init__(self, value):
        super(iunicode, self).__init__(value)
        self.value = value

    def __eq__(self, other):
        if isinstance(other, str) or isinstance(other, unicode):
            return self.value.lower() == other.lower()
        if isinstance(other, self.__class__):
            return other == self.value


def custom_getattribute(self, name):
    val = object.__getattribute__(self, name)
    if name == "username":
        val = iunicode(val)
    return val

def auth_user_save(self, *args, **kwargs): # Ensures lowercase usernames
    username = self.username
    if username and type(username) in [unicode, str, iunicode]:
        self.username = username.lower()   # Only lower case allowed
    super(User, self).save(*args, **kwargs)

User.__getattribute__ = custom_getattribute
User.save = MethodType(auth_user_save, None, User)
#####################################################

我测试了它,并按预期工作。:D

因此,这是 测试用例

from django.test.testcases import TestCase

def create_user(data='testuser'):
    email = '%s@%s.com' % (data, data)
    user = G(User, username=data, email=email, is_active=True)
    user.set_password(data)
    user.save()
    return user

class UsernameCaseInsensitiveTests(TestCase):

    def test_user_create(self):
        testuser = 'testuser'
        user = create_user(testuser)
        # Lowercase
        self.assertEqual(testuser, user.username)
        # Uppercase
        user.username = testuser.upper()
        user.save()
        self.assertEqual(testuser, user.username)

def test_username_eq(self):
    testuser = 'testuser'
    user = create_user(testuser)
    self.assertTrue(isinstance(user.username, iunicode))
    self.assertEqual(user.username, testuser)
    self.assertEqual(user.username, testuser.upper())
    self.assertTrue(user.username == testuser.upper())
    self.assertTrue(testuser.upper() == user.username)
    self.assertTrue(user.username == iunicode(testuser.upper()))

隐式不区分大小写的数据库查询

###################### QuerySet #############################
def _filter_or_exclude(self, negate, *args, **kwargs):
    if 'username' in kwargs:
        kwargs['username__iexact'] = kwargs['username']
        del kwargs['username']
    if args or kwargs:
        assert self.query.can_filter(),\
        "Cannot filter a query once a slice has been taken."
    from django.db.models import Q
    clone = self._clone()
    if negate:
        clone.query.add_q(~Q(*args, **kwargs))
    else:
        clone.query.add_q(Q(*args, **kwargs))
    return clone

from django.db.models.query import QuerySet
QuerySet._filter_or_exclude = _filter_or_exclude
#############################################################

这将允许User.objects.get(username='yugal')User.objects.get(username='YUGAl')产生相同的用户。



 类似资料:
  • 我发现在我的应用程序中,使用spring security的安全性在登录时不会检查我的用户名的大小写。 我有这个代码: 我不知道为什么当我对用户名使用不同的特殊情况时,spring的身份验证允许所有情况。有人能帮我吗? 谢啦

  • 于是我在这里看到:https://firebase . Google . com/docs/auth/web/account-linking # link-auth-provider-credentials-to-a-user-account现在可以在Firebase中链接用户账号了。我还看到Firebase提供了匿名认证的功能,它为一个用户创建一个用户会话,不需要任何凭证。 在我们的应用程序中,

  • 我有一个db表说,在Postgres传给另一个团队,有一个列名说,。现在我试图使用PG指挥官来查询这个列名称上的表。 然后它就回来了 错误:列"first_Name"不存在 不确定我是在做一些愚蠢的事情,还是有解决这个问题的方法,我错过了?

  • 我目前正在为Spring Boot网站编写一个评论系统,它将基于一个简单的REST API。 为了让人们删除或更新他们之前发布的评论,我想在Cookie中存储一个唯一的令牌来记住/识别他们。用户不需要注册以便发表评论。当用户删除cookie或cookie过期时,将无法取回删除/修改注释的权限。 当然,我自己使用过滤器来实现这样的功能是可能的,但是我想知道在Spring中是否有一种标准的方法(可能是

  • 我尝试postman使用用户名和密码连接到我的一个web服务,每次更改用户名时,即使用户名与我放在属性文件中的用户名不相同,请求也会被验证

  • 我一直在寻找使用各种AWS服务来处理我们下一个主要项目的基础设施。我们开始研究EC2实例上的docker容器,但在进一步研究AWS Lambda之后,这似乎是一条值得探索的道路。 使用AWS Lambda范例,我们只需使用Lambda函数作为逻辑粘合剂,将数据和事件(来自其他AWS服务)保存在一起。 例如,如果我们产品的用户创建了一个新记录,AWS Lambda可以在该事件中触发,我们可以调用La