J. Валидация пароля

После того как пользователь ввёл свои данные в требуемом формате, можно позаботиться и о пароле.

Напишите функцию password_validation, которая принимает один позиционный параметр — пароль, и следующие именованные параметры:

  • min_length — минимальная длина пароля, по умолчанию 8;
  • possible_chars — строка символов, которые могут быть в пароле, по умолчанию латинские буквы и цифры;
  • at_least_one — функция возвращающая логическое значение, по умолчанию str.isdigit.

Если переданный позиционный параметр не является строкой, вызовите исключение TypeError.

А так же реализуйте собственные исключения:

  • MinLengthError — вызывается, если пароль меньше заданной длины;
  • PossibleCharError — вызывается, если в пароле используется недопустимый символ;
  • NeedCharError — вызывается, если в пароле не найдено ни одного обязательного символа.

Проверка условий должна происходить в порядке указанном в задании.

Так как, хороший разработчик никогда не хранит пароли в открытом виде, функция, в случае успешного завершения, возвращает хеш пароля. Для этого воспользуйтесь функцией sha256 из пакета hashlib и верните его шестнадцатеричное представление.

В решении не должно быть вызовов требуемых функций.

Пример

Ввод

print(password_validation("Hello12345"))

Вывод

67698a29126e52a6921ca061082783ede0e9085c45163c3658a2b0a82c8f95a1

Ввод

print(password_validation(
    "$uNri$e_777",
    min_length=6,
    at_least_one=lambda char: char in "!@#$%^&*()_"
))

Вывод

Вызвано исключение PossibleCharError

Решение

Продолжение серии задач на валидацию пользовательских данных.

По сути простая задача:
Проверяем передали ли нам строку, если нет, вызываем исключение.
Проверяем длину, если меньше заданого значения, вызываем исключение.
Проверяем все ли символы имеют допустимое значение, если нет – вызываем исключение.
Проверяем есть ли среди символов символ из списка обязательных, если нет – вызываем исключение.

По окончании всех проверок с помощью функций модуля hashlib генерируем и возвращаем hash пароля.

Посмотреть код

Решение

Python
import hashlib


class MinLengthError(Exception):
    pass


class PossibleCharError(Exception):
    pass


class NeedCharError(Exception):
    pass


possible_password_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'


def password_validation(password, min_length=8,
                        possible_chars=possible_password_chars,
                        at_least_one=str.isdigit) -> str:
    if not isinstance(password, str):
        raise TypeError
    if len(password) < min_length:
        raise MinLengthError
    if any([char not in possible_chars
            for char in password]):
        raise PossibleCharError
    if not any([at_least_one(char) for char in password]):
        raise NeedCharError

    hash_object = hashlib.sha256()
    hash_object.update(password.encode())
    hash = hash_object.hexdigest()

    return hash
Подписаться
Уведомить о
guest
5 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Расул
Расул
06.09.2024 17:03

Подскажите пожалуйста, почему это решение не проходит

import hashlib

class MinLengthError(Exception):
pass

class PossibleCharError(Exception):
pass

class NeedCharError(Exception):
pass

def password_validation(
password,
min_length=8,
possible_chars=’abcdefghijklmnopqrstuvwxyz0123456789′,
at_least_one=str.isdigit
):
if not isinstance(password, str):
raise TypeError
if len(password) < min_length:
raise MinLengthError
if any([char.lower() not in possible_chars for char in password]):
raise PossibleCharError
if not any([at_least_one(char) for char in password]):
raise NeedCharError

hash_object = hashlib.sha256()
hash_object.update(password.encode(‘utf-8’))
hex_dig = hash_object.hexdigest()
return hex_dig
принципиальных отличий между вашим и моим решением нет. Отличие одно – у вас в possible_char предложены заглавные буквы, а у меня для этого предусмотрено char.lower()
Вот ваше решение:

import hashlib

class MinLengthError(Exception):
  pass

class PossibleCharError(Exception):
  pass

class NeedCharError(Exception):
  pass

possible_password_chars = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789’

def password_validation(password, min_length=8,
            possible_chars=possible_password_chars,
            at_least_one=str.isdigit) -> str:
  if not isinstance(password, str):
    raise TypeError
  if len(password) < min_length:
    raise MinLengthError
  if any([char not in possible_chars
      for char in password]):
    raise PossibleCharError
  if not any([at_least_one(char) for char in password]):
    raise NeedCharError

  hash_object = hashlib.sha256()
  hash_object.update(password.encode())
  hash = hash_object.hexdigest()

  return hash

Последний раз редактировалось 3 месяцев назад Сергей Клочко ем
Ольга
Ольга
21.11.2024 00:32

Сергей, здравствуйте.
Позвольте еще раз задать тот же вопрос, который озвучивал Расул, и на который Вы уже ответили. Вернее, даже не задать вопрос, а уточнить нюансы для окончательного их понимания.
Вероятно, исходно неверный подход к решению вызывает некоторая путаница, связанная с решением задач G. Валидация имени, H. Валидация имени пользователя и I. Валидация пользователя. Там мы используем .lower() с целью сопоставления имени/фамилии с «сокращенной» версией алфавита (только в нижнем регистре).
И вот в этой, текущей, задаче мы по аналогии делаем так же. Интерпретатор выдает желаемый результат. И мы считаем (неверно), что всё в порядке.
Но мы не учитываем, что здесь речь идет о пароле. В котором, если учитывать значимость вопроса безопасности, регистр важен. В результате мы отправляем на проверку решение, в котором предусмотрена версия алфавита, включающая, например, только строчные буквы (используя при этом .lower() и думая, что всё хорошо). Но тест Яндекса выдает неудовлетворительный результат, поскольку тестирование «настроено», в том числе, на то, чтобы валидировать пароль на регистр (то есть не только на строчные, но и на прописные буквы).
Правильно ли я поняла суть? Скажите, пожалуйста.
 
А еще возник вопрос по необходимости использования списочных выражений (генераторов списков) в all([…]), any([…]).
Скажите, пожалуйста, а можно использовать просто генераторное выражение (генератор)? Ведь нам же, исходя из поставленных задач, не требуется сам список (например, для его вывода).
Если я правильно поняла из освоенной по разным источникам информации, списочные выражения заранее генерируют весь список. А генератор останавливается при обнаружении первого совпадения (в случае any) или несовпадения (в случае all). Т.е., получается, генератор не перебирает и, что важно, не запоминает лишние сведения. Поэтому, возможно, скорость выполнения не будет сильно отличаться, если при использовании генератора совпадение/несовпадение будет в конце последовательности (а может быть и будет, если в начале). Но генераторы точно позволяют экономить память, а ведь производительность же всегда важна…
Вот, например, Яндекс принимает, в том числе, такую вариацию на тему:

import hashlib


class CyrillicError(Exception):
    pass


class CapitalError(Exception):
    pass


class MinLengthError(Exception):
    pass


class PossibleCharError(Exception):
    pass


class NeedCharError(Exception):
    pass


def password_validation(password, min_length=8,
                        possible_chars='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
                        at_least_one=lambda x: x.isdigit()) -> str:
    if not isinstance(password, str):
        raise TypeError
    if len(password) < min_length:
        raise MinLengthError
    if not all(i in possible_chars for i in password):
        raise PossibleCharError
    if not any(at_least_one(i) for i in password):
        raise NeedCharError
    return hashlib.sha256(password.encode()).hexdigest()

Уместны ли мои размышления? Очень важно Ваше мнение. Заранее спасибо.  

Ольга
Ольга
Ответить на  Сергей Клочко
21.11.2024 10:43

Сергей, большое… нет, вот прямо огромное спасибо!