微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

############ 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')产生相同的用户

解决方法

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

我究竟做错了什么 ?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。