Grails: Хитрые грабли на примере сохранения и валидации пароля


Часто натыкаюсь на такую запись:

class User {
  String email
  ...
  String password

  static constraints {
        password(nullable: false, blank: false, minSize: 6)
  }
}

И потом делают валидацию по этому полю а перед сохранением перезаписывают его хешом, например:

user.password = params.password.encodeAsSHA256()

Это некрасиво потому что в этом случае описание поля идёт в разрез с его презентацией на уровне БД. Описание модели должно описывать доменный объект с аспектом как его сохранять в БД, и валидациия указывается уровня БД а не биндинга в контроллере.
Об этом нужно помнить. Например при сохранении не уникального значение в unique поле вы получите исключении на уровне БД а не ошибку на уровне валидатора формы.
Кстати этот пример плох ещё тем что пароль не посолили.

Хеш будет иметь всегда фиксированный размер (в 64 символа в случае с SHA256). Даже у пустой строки, ага.
Если не указан максимальный размер текстового поля то его размер на уровне БД будет 255 символов. А использовать будем всегда только 64, т.е. имеем оверхед.
Или например если вы не указали максимальный размер поля, то он не будет валидироватся на уровне формы и вы получите исключение при сохранении в БД — ещё один наглядный пример что валидация форм не всегда коррелирует с презентацией на уровне БД.

Значит нам нужно указать размер поля, например так:

password(nullable: false, blank: false, maxSize: 64)

Хочу обратить внимание что ещё один аргумент против указания характеристик пароля в описании поля в которое будет сохранён его хеш, потому что в таком случае пароль будет ограничен в 64 символа.
Ограничивать размер пароля совершенно глупо, чем длиннее пароль тем выше его надёжность. Я например могу использовать целую фразу и вставлять её автоматически например из брелока.
Какая вам разница какой длины мой пароль? Хоть весь текст Войны и Мира, всё равно ведь в вашей БД он займёт 64 символа. Главное чтобы уложилось в разумное ограничение на длину POST запроса.
Кстати также глупо ограничивать или навязывать мне набор символов, например чтобы обязательно были в нём цифры. Пароль из шестнадцати обычных латинских букв надёжней пароля из шести крякозяблов «qwert$123».

Заключение

Я бы вам посоветовал вот такое описание поля пароля

password(nullable: false, size: 64..64, bindable: false)

Где размер строго 64 символа на хеш (зависит от алгоритма хеширования), и ещё отключен биндинг на всякий пожарный.

При этом валидацию пароля делайте сами, вручную при этом я бы вам советовал на самом деле проверять только что он не пустой, ну в крайнем случае минимальный размер.

Надеюсь эта маленькая заметочка наглядно показала вам сразу несколько ловушек в Grails.
По хорошему для пароля нужно создать отдельный пользовательский тип или constraint.
У кого есть свободное время, сделайте пожалуйста плагин, я был бы очень благодарен.

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s