在Django中,在验证密码时如何访问请求变量?

huangapple go评论59阅读模式
英文:

In Django, how do I access request variable when validating password?

问题

在Django中,我需要创建一个自定义密码验证器,它需要从数据库中读取密码策略配置。为了做到这一点,我需要客户端ID,通常嵌入在请求变量中,但在这种情况下,请求不可用。是否有其他方法来实现这一目标?

class MinimumLengthValidator:
    """
    验证密码是否达到最小长度要求。
    """
    def __init__(self, min_length=8):
        self.min_length = min_length
        # 在这里获取客户端配置中的最小长度,通常是 request.client.config.password_min_length,例如,其值为 10
英文:

In Django I need to create a custom password validator which needs to read from the DB to fetch password policy configuration. To do this I need the client ID which is usually embedded in the request variable but in this case, request it is not available. Is there an alternative method to achieve this?

class MinimumLengthValidator:
    """
    Validate whether the password is of a minimum length.
    """
    def __init__(self, min_length=8):
        self.min_length = min_length
        #get minimum length from client config here, typically request.client.config.password_min_length e.g. value is 10

答案1

得分: 0

Short answer: 在这里你会找到一切信息:集成验证

Long answer:
我认为最常见的方法是始终使用自定义的用户模型。这意味着从AbstractUser派生的"自己的"用户模型。在那里,您可以覆盖字段、添加字段和方法。然后,通过使用该用户模型的ModelForm,完全可以创建一个用户。因此,从您的视图开始,您可以将客户端ID传递给所提到的ModelForm__init__()方法,并像@ybl建议的那样"传递下去"。

但是,看起来您的项目完全运行在django.contrib.auth上,没有对用户模型进行任何修改。因此,您说上面的解决方案"太多"来添加一个验证器是正确的。(但很可能在将来您会添加一个自定义用户模型,所以请考虑这个选项)。

编写您的自定义验证器

class CustomValidator:
    def __init__(self, client_id, pw_config):
        self.client_id = client_id
        self.pw_config = pw_config

    def validate(self, user=None):
        if self.client_id != xx and self.pw_config != xx:
            raise ValidationError(
                "pw not valid", 
                code='clientID_not_pwConfig',
                params={'pw_config': self.pw_config, 'client_id': self.client_id},
            )
        # 如果密码有效,返回None

    def get_help_text(self):
        return _(
            f"Your {self.client_id} does not match pw_config"
        )

然后在您的视图中(链接在上述"short answer"中):

from django.contrib.auth.password_validation import get_password_validators, validate_password

def your_view(request):
    client_id = get_client_id()
    pw_config = get_pw_config()
    standard_validators = get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
    custom_validator = CustomValidator(client_id, pw_config)
    all_validators = standard_validators + [custom_validator]
    
    if validate_password(
        password,  # 替换为您的需求
        user=None,  # 替换为您的需求
        password_validators=all_validators
    ) is not None:
        # 您的密码有效
    else:
        # 您的密码无效
英文:

Short answer: You'll find everything here: Integrating validation

Long answer: <br>
I think the most common way is having a custom User model anyways. Meaning having your "own" User model which is subclassed from AbstractUser. There you can overwrite fields, add fields and methods. Fine. Then it totally makes sense to create a User via a ModelForm off that User model. Therefore, starting from your view, you could pass the client ID to the __init__() method of mentioned ModelForm and "pass it down the chain" as @ybl suggested.

But it seems like your project is running entirely on django.contrib.auth with no modification at all to the User model. Hence you are right at saying that above solution is "a lot" just for adding one validator. (Most likely though you are going to add a custom user model anyways in the future (more info), so consider that option).

Write your custom validator:

class CustomValidator:
    def __init__(self, client_id, pw_config):
        self.client_id = client_id
        self.pw_config = pw_config

    def validate(self, user=None):
        if self.client_id != xx and self.pw_config != xx:
            raise ValidationError(
                &quot;pw not valid&quot;, 
                code=&#39;clientID_not_pwConfig&#39;,
                params={&#39;pw_config&#39;: self.pw_config, &#39;client_id&#39;: self.client_id},
            )
        # in case pw is valid return None


    def get_help_text(self):
        return _(
            f&quot;Your {self.client_id} does not match pw_config&quot;
        )

Then in your view (resources linked as "short answer" above):

from django.contrib.auth.password_validation import get_password_validators, validate_password


def your_view(request):
    client_id = get_client_id()
    pw_config = get_pw_config()
    standard_validators = get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
    custom_validator = CustomValidator(client_id, pw_config)
    all_validators = standard_validators + [custom_validator]
    
    if validate_password(
        password,  # replace to your needs
        user=None,  # replace to your needs
        password_validators=all_validators
    ) is not None:
        # your pw is valid
    else:
        # your pw is not valid

huangapple
  • 本文由 发表于 2023年6月15日 16:09:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76480382.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定