簡體   English   中英

在django中使用電子郵件而不是登錄名

[英]Using email instead of login name in django

首先,這不是如何對電子郵件/密碼對進行身份驗證的問題,而是如何生成邏輯,如果您願意,還可以使用漂亮的數據結構。

我想在給定的django項目中使用電子郵件作為用戶名。 但是,我無法重新使用auth.User模型提供的字段,原因至少有兩個:

  1. auth.User.username的字段max_length是30個字符,對於某些電子郵件地址可能不夠。

  2. auth.User.email不是唯一的 - 顯然不能滿足前提條件,即用戶名必須是唯一的。

因此,一個顯而易見的方法是將用戶名存儲在自定義配置文件中,該配置文件鏈接到auth.User。 在這種情況下,我們必須處理以下問題:

  1. 為auth.User.username生成唯一的用戶名 - 電子郵件的md5哈希應該沒問題嗎?
  2. 完全遺漏auth.User.email為空 - 因為它只有75個字符長,而根據RFC 5321( 有效電子郵件地址的最大長度是多少? ),電子郵件可以長達256個字符。

以下問題源於提出的解決方案:

  1. 一個是無法為密碼重置等標准操作重用內置視圖/模板
  2. 如果電子郵件更改,則必須更新auth.User.username

為了增加石油,django開發人員不太可能在任何可預見的未來修復此限制 - 請參閱http://code.djangoproject.com/ticket/11365

所以問題是:有沒有其他方法可以做到這一點你是否看到上面提出的解決方案有任何其他缺點?

謝謝!

我有一個客戶有一個自1995年以來一直在增加的商業網站(是的,我們在這里談論早期采用者)。 無論如何,他們已經建立了一個用戶群,而且這些名字完全不符合Django的用戶名。

我看了幾個方法來處理它,它們都感覺像黑客(這是2007年的夏天),所以我說擰了它並直接攻擊contrib.auth.models.User。 我只需更改大約10行代碼,增加字段大小,並調整驗證器。 從那以后我們做了兩次升級--0.97-pre => 1.0,1.0 => 1.1.1 - 每次只需要15分鍾來“移植黑客”。

它不漂亮,而且我可能會像這樣在地獄中燃燒,但這樣做的時間比我能想到的任何其他東西花費的時間少,前端端口完全沒有問題。

我寫了一個解釋我解決這個問題的方法: 使用電子郵件地址進行Django身份驗證 它基本上包括:

  • 為電子郵件身份驗證創建自定義授權后端。
  • 對用戶創建表單進行子類化,以將電子郵件地址添加為必填字段。
  • 在創建和登錄表單中隱藏用戶的用戶名字段。
  • 在視圖中隨機生成用於處理創建表單的用戶名。
  • 手動為電子郵件列添加唯一索引(Yuck!)

我的解決方案仍有2個問題。 首先,手動創建數據庫索引並不好。 其次,電子郵件仍然限制在75個字符(我沒有任何問題移植系統有大約8,000個用戶)。 但是,它與Django和第三方應用程序的其余部分相當不錯。

我也必須承認我會在地獄中燃燒。 我最近部署了一個小應用程序,我將用戶的電子郵件強制插入,將其切成30個字符並將其設置為用戶名。 我想到了,有什么可能性? 並經歷了它。 拿了幾行代碼和瞧。

我認為75字符的上限是這樣設置的,因為人們通常沒有長時間的個人電子郵件。 這只是空間保護的問題,因為所有那些未使用的字節都將被保留(即NULL和更短/更小的值不是免費的)。

我根據Dominique的答案編寫了一個解決方案,其中包括安全性改進和一些額外的功能,如區分大小寫的身 如果您願意,可以直接從pypi安裝

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.conf import settings

###################################
"""  DEFAULT SETTINGS + ALIAS   """
###################################


try:
    am = settings.AUTHENTICATION_METHOD
except:
    am = 'both'
try:
    cs = settings.AUTHENTICATION_CASE_SENSITIVE
except:
    cs = 'both'

#####################
"""   EXCEPTIONS  """
#####################


VALID_AM = ['username', 'email', 'both']
VALID_CS = ['username', 'email', 'both', 'none']

if (am not in VALID_AM):
    raise Exception("Invalid value for AUTHENTICATION_METHOD in project "
                    "settings. Use 'username','email', or 'both'.")

if (cs not in VALID_CS):
    raise Exception("Invalid value for AUTHENTICATION_CASE_SENSITIVE in project "
                    "settings. Use 'username','email', 'both' or 'none'.")

############################
"""  OVERRIDDEN METHODS  """
############################


class DualAuthentication(ModelBackend):
    """
    This is a ModelBacked that allows authentication
    with either a username or an email address.
    """

    def authenticate(self, username=None, password=None):
        UserModel = get_user_model()
        try:
            if ((am == 'email') or (am == 'both')):
                if ((cs == 'email') or cs == 'both'):
                    kwargs = {'email': username}
                else:
                    kwargs = {'email__iexact': username}

                user = UserModel.objects.get(**kwargs)
            else:
                raise
        except:
            if ((am == 'username') or (am == 'both')):
                if ((cs == 'username') or cs == 'both'):
                    kwargs = {'username': username}
                else:
                kwargs = {'username__iexact': username}

                user = UserModel.objects.get(**kwargs)
        finally:
            try:
                if user.check_password(password):
                    return user
            except:
                # Run the default password hasher once to reduce the timing
                # difference between an existing and a non-existing user.
                UserModel().set_password(password)
                return None

    def get_user(self, username):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=username)
        except UserModel.DoesNotExist:
            return None

對於沒有更改模型的身份驗證[用戶名,電子郵件],只需添加后端:

方法認證[電子郵件,用戶名]

我只是使用這個djangosnippet ,用戶可以使用他們的用戶名或他們的電子郵件。
但它不會解決75個字符的限制,只是一個方便的片段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM