ASP.NET MVC: достаточно ли проверки аннотаций данных?

Я широко использую проверку аннотаций данных в ASP.NET MVC 2. Эта новая функция значительно сэкономила время, поскольку теперь я могу определять как проверку на стороне клиента, так и проверку на стороне сервера в одном месте. Однако, проводя подробное тестирование, я понял, что кому-то довольно легко обойти проверку на стороне сервера, если бы я использовал только проверку аннотации данных. Например, если я определил обязательное поле, пометив свойство с помощью атрибута [Required] и поместил текстовое поле для этого обязательного поля в форме, пользователь мог бы просто удалить текстовое поле из DOM (что можно легко сделать с помощью Firebug) и теперь проверка аннотации данных не будет запускаться для этого свойства во время связывания модели внутри контроллера. Чтобы убедиться, что «требуемая» проверка запускается,

Какова общая рекомендация по валидации? Достаточно ли валидации аннотации данных? Или необходимо повторить проверку, чтобы убедиться, что проверки запускаются во всех ситуациях?

Последующий комментарий: Судя по ответам ниже, кажется, что я не могу полагаться только на проверку связывателя модели и аннотации данных. Поскольку мы пришли к выводу, что требуется дополнительная проверка на стороне сервера, существует ли простой способ для моего уровня обслуживания инициировать проверку на основе того, что было определено в аннотациях данных? Кажется, что это даст нам лучшее из обоих слов ... нам не нужно будет повторять код проверки, но мы по-прежнему обеспечим выполнение проверки, даже если Model Binder не вызовет ее.

Я собираюсь опубликовать этот дополнительный комментарий как отдельный вопрос, так как он ставит вопрос, отличный от исходного.

13.10.2009 06:17:56
Ответ Koritnik отвечает на ваш последующий запрос. Я делаю свою проверку аналогично ответу, который он опубликовал. Одно и то же определение DataAnnotation может использоваться для проверки как сервера, так и клиента.
Matt Kocaj 14.10.2009 18:34:23
Проверка аннотации данных хороша, если вам предоставлены атрибуты проверки и сама структура. Поведение с Обязательным было изменено для ASP.NET MVC 2 RTM из-за отзывов сообщества, поэтому [Обязательный] теперь работает так, как вы ожидаете. Опционально проверьте: Блок валидации (Enterprise Library), xVal, NHibernate Validators (предположительно не зависит от NHibernate ORM).
miha 21.03.2010 18:58:20
"I'm going to post this follow-up comment as a separate question, as it poses a different question than the original one."Ссылка на это не будет плохой идеей, а?
Sinjai 14.07.2017 18:06:59
5 ОТВЕТОВ
РЕШЕНИЕ

Я думаю, чтобы быть бдительным в отношении безопасности, вы должны сделать так, чтобы проверка сервера была приоритетом и чтобы это всегда было вашим запасным вариантом. Проверка вашего сервера должна работать без проверки клиента. Проверка клиента - это больше для UX, и это имеет первостепенное значение для вашего дизайна, это вторично по отношению к безопасности. Имея это в виду, вы обнаружите, что повторяете свою проверку. Часто целью является попытка спроектировать ваше приложение так, чтобы проверка сервера и клиента могла быть максимально интегрирована, чтобы уменьшить объем работы, необходимой для проверки на сервере и клиенте. Но будьте уверены, вы должны сделать оба.

Если обход проверки клиента (посредством манипулирования DOM) позволяет избежать проверки сервера (что, по-видимому, вы указываете), тогда проверка вашего сервера для этого экземпляра может не использоваться надлежащим образом. Вы должны снова вызывать проверку вашего сервера в действии контроллера или на уровне службы. Сценарий, который вы описываете, не должен побеждать проверку вашего сервера.

С описанным вами сценарием метода атрибутов DataAnnotation должно быть достаточно. Кажется, вам просто нужно внести несколько изменений в код, чтобы убедиться, что проверка вашего сервера также запускается при отправке формы.

18
13.10.2009 08:00:07

DataAnnotation, конечно, недостаточно. Я широко использую его также для предварительной проверки моих обращений к модели предметной области, чтобы получать более качественные отчеты об ошибках и как можно раньше отказывать.

Однако вы можете настроить модель DataAnnotation самостоятельно, чтобы убедиться, что свойства с [Обязательно] ДОЛЖНЫ быть опубликованы. (свяжемся с кодом позже сегодня).

ОБНОВЛЕНИЕ Получите источник для связывателя модели DataAnnotations и найдите эту строку в DataAnnotationsModelBinder.cs

// Only bind properties that are part of the request
if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) {

Измените это на

// Only bind properties that are part of the request
bool contextHasKey = bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey);
bool isRequired = GetValidationAttributes(propertyDescriptor).OfType<RequiredAttribute>().Count() > 0;
if (contextHasKey || (!contextHasKey && isRequired)) {
2
13.10.2009 18:21:16
Конечно, я опубликовал это до того, как уйти на работу (на работе все еще сейчас), поэтому нет времени кодировать :(. Я немного изменил связыватель, так как он не проверял вложенные объекты и сбрасывал недействительные свойства в null, с чем я не согласился, см. Stackoverflow .com / questions / 820468 /… С тех пор я также добавил необходимые проверки, но хотел бы проверить их, когда вернусь домой, прежде чем публиковать их
Martijn Laarman 13.10.2009 11:39:47
Обновленный с кодом, но я не в состоянии проверить это должным образом, сделаю это снова завтра, но отправил это, таким образом, возможно, Вы сможете оценить это быстрее. Он проходит модульные тесты проекта, но, честно говоря, в этом случае нет тестовых тестов: D.
Martijn Laarman 13.10.2009 18:22:48
Спасибо Мартейн. Мне придется оставить это на другой день, так как это потребует внесения изменений в источник. Сейчас я собираюсь принять ваше (и другие) предложение и убедиться, что проверка также дублируется в доменной модели.
Johnny Oshika 14.10.2009 06:20:05
Конечно, нет проблем. Было бы здорово, если бы вы могли переложить проверки целостности данных в DataAnnotations. Таким образом, ваша модель домена должна только проверять бизнес-правила.
Martijn Laarman 14.10.2009 06:40:55
Модель домена все еще должна вызывать DataAnnotations, хотя вы никогда не знаете, когда хотите экспортировать домен в виде отдельной DLL :).
Martijn Laarman 14.10.2009 06:42:25

Я связал xVal с DataAnnotations и написал свой собственный фильтр действий, который проверяет любые параметры типа сущностей в целях проверки. Таким образом, если какое-либо поле отсутствует в обратной передаче, этот валидатор заполнит словарь ModelState, следовательно, модель недействительна.

Предпосылки:

  • мои объекты сущности / модели все реализуют IObjectValidatorинтерфейс, который объявляет Validate()метод.
  • мой класс атрибута называется ValidateBusinessObjectAttribute
  • библиотека проверки xVal

Код фильтра действий:

public void OnActionExecuting(ActionExecutingContext filterContext)
{
    IEnumerable<KeyValuePair<string, object>> parameters = filterContext.ActionParameters.Where<KeyValuePair<string, object>>(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator);
    foreach (KeyValuePair<string, object> param in parameters)
    {
        object value;
        if ((value = param.Value) != null)
        {
            IEnumerable<ErrorInfo> errors = ((IObjectValidator)value).Validate();
            if (errors.Any())
            {
                new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key);
            }
        }
    }
}

Мое действие контроллера определяется следующим образом:

[ValidateBusinessObject]
public ActionResult Register(User user, Company company, RegistrationData registrationData)
{
    if (!this.ModelState.IsValid)
    {
        return View();
    }
    ...
}
7
14.10.2009 06:30:12
у вас есть более подробный пример того, как использовать этот или загружаемый проект, возможно
Aivan Monceller 21.12.2010 03:51:19
@geocine: Где, кажется, проблема? Вы используете MVC1? Более новые версии не требуют этого, потому что они автоматически проверяют параметры строгого типа ... Но этот пример здесь так же подробен, как и должно быть на самом деле. Так в чем же проблема?
Robert Koritnik 21.12.2010 06:08:01
Я только что прошел мимо, и я новичок в aspmvc, читающий о проблемах проверки. Я забыл, что использую MVC 2. мой плохой.
Aivan Monceller 21.12.2010 07:39:30

Я написал свой собственный ValidationService для MVC 1.0, скопировав шаблоны как из DataAnnotationsRuleProvider от xVal, так и из DataAnnotationsModelBinder от Microsoft (и комментариев Мартийна). Интерфейс сервиса ниже:

public interface IValidationService
{
    void Validate(object instance);

    IEnumerable<ErrorInfo> GetErrors(object instance);
}

public abstract class BaseValidationService : IValidationService
{
    public void Validate(object instance)
    {
        var errors = GetErrors(instance);

        if (errors.Any())
            throw new RulesException(errors);
    }

    public abstract IEnumerable<ErrorInfo> GetErrors(object instance);
}

Служба - это средство проверки правильности, которое просматривает дерево свойств экземпляра объекта, которое оно получает, и фактически выполняет атрибуты проверки, которые оно находит для каждого свойства, создавая список объектов ErrorInfo, когда атрибуты недопустимы. (Я бы опубликовал весь источник, но он был написан для клиента, и я пока не знаю, уполномочен ли я сделать это.)

Затем вы можете иметь свои контроллеры, сервисы бизнес-логики, которые будут явно вызывать проверку, когда вы будете готовы, вместо того, чтобы полагаться исключительно на связыватель модели для проверки.

Есть несколько других подводных камней, о которых вы должны знать:

  • Атрибут DataTypeAttribute по умолчанию в аннотациях данных фактически не выполняет никакой проверки типа данных, поэтому вам нужно написать новый атрибут, который фактически использует регулярные выражения xVal (или что-то еще) для выполнения проверки типа данных на стороне сервера.
  • xVal не просматривает свойства для создания проверки на стороне клиента, поэтому вы можете внести некоторые изменения, чтобы получить более надежную проверку на стороне клиента.

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

2
4.11.2009 16:04:22

См. CodeProject Проверка входных данных на стороне сервера с использованием аннотаций данных

Проверка ввода может выполняться автоматически на стороне клиента в ASP.NET MVC или явно проверять модель на соответствие правилам. Этот совет расскажет, как это можно сделать вручную на стороне сервера приложений ASP.NET или в коде репозитория приложений WPF.

        // Use the ValidationContext to validate the Product model against the product data annotations
        // before saving it to the database
        var validationContext = new ValidationContext(productViewModel, serviceProvider: null, items:null);
        var validationResults = new List<ValidationResult>();

        var isValid = Validator.TryValidateObject(productViewModel, validationContext,validationResults, true);
1
6.12.2012 21:04:42