2009-10-13 12 views
27

Używam sprawdzania poprawności danych w programie ASP.NET MVC 2. Ta nowa funkcja stanowi olbrzymią oszczędność czasu, ponieważ jestem teraz w stanie zdefiniować zarówno walidację po stronie klienta, jak i walidację po stronie serwera w jednym miejscu. Jednak podczas przeprowadzania szczegółowych testów zdałem sobie sprawę z tego, że łatwo jest omijać walidację po stronie serwera, jeśli polegam wyłącznie na sprawdzaniu poprawności danych. Na przykład, jeśli zdefiniowałem wymagane pole, przypisując właściwość atrybutem [Wymagane] i umieściłem pole tekstowe dla tego wymaganego pola w formularzu, użytkownik mógłby po prostu usunąć pole tekstowe z DOM (co można łatwo zrobić za pomocą Firebug) a teraz sprawdzanie adnotacji danych nie zostanie uruchomione na tej właściwości podczas ModelBinding wewnątrz kontrolera. Aby upewnić się, że "wymagane" sprawdzanie poprawności jest uruchamiane, mogę powtórzyć sprawdzanie poprawności po wystąpieniu zdarzenia ModelBinding, ale wtedy będę powtarzać logikę sprawdzania poprawności.ASP.NET MVC: czy poprawność adnotacji danych jest wystarczająca?

Jakie są zalecenia wszystkich osób w zakresie walidacji? Czy weryfikacja danych jest wystarczająca? Czy weryfikacja musi zostać powtórzona, aby zapewnić, że sprawdzanie poprawności zostanie uruchomione we wszystkich sytuacjach?

Follow-up komentarz: podstawie poniższych odpowiedzi, wydaje się, że nie mogę polegać na walidację modelu Binder i danych adnotacji w spokoju. Ponieważ dochodzimy do wniosku, że wymagana jest dodatkowa walidacja po stronie serwera, czy istnieje możliwość łatwego sprawdzenia poprawności mojej warstwy usług na podstawie definicji zdefiniowanej w Adnotacjach danych? Wygląda na to, że dzięki temu uzyskamy najlepsze z obu słów ... nie będziemy musieli powtarzać kodu walidacyjnego, ale nadal zapewniamy, że sprawdzanie poprawności zostanie wykonane, nawet jeśli moduł Binder go nie wyzwoli.

Zamierzam opublikować ten dodatkowy komentarz jako osobne pytanie, ponieważ stanowi ono inne pytanie niż pierwotne.

+0

odpowiedź Koritnik za odpowiedzi na swoje kontynuacji zapytania. Przeprowadzam moją walidację podobną do odpowiedzi, którą wysłał. Ta sama definicja DataAnnotation może być używana zarówno do sprawdzania poprawności serwera, jak i klienta. –

+1

Sprawdzanie poprawności danych jest poprawne, jeśli dostarczone atrybuty sprawdzania poprawności i sama ramka będą dla Ciebie odpowiednie. Zachowanie w Required zostało zmienione dla ASP.NET MVC 2 RTM ze względu na opinie społeczności, więc [Wymagane] działa teraz tak, jak można się spodziewać. Opcjonalnie, sprawdź: blokowanie sprawdzania poprawności (biblioteka korporacyjna), xVal, walidatory NHibernate (rzekomo nie ma zależności od NHibernate ORM). – miha

+0

'" Zamierzam opublikować ten dodatkowy komentarz jako osobne pytanie, ponieważ stawia ono inne pytanie niż oryginalne. "" Link do tego nie byłby złym pomysłem, co? – Sinjai

Odpowiedz

18

myślę czujności dotyczącej bezpieczeństwa należy wybrać spraw, aby walidacja serwera była priorytetem i upewnij się, że jest to zawsze awaryjne. Sprawdzanie poprawności serwera powinno działać bez sprawdzania poprawności klienta. Sprawdzanie poprawności klienta jest bardziej dla UX i tho, co jest najważniejsze dla twojego projektu, jest drugorzędne w stosunku do bezpieczeństwa. Mając to na uwadze, powtarzasz swoją walidację. Celem jest często próba zaprojektowania aplikacji tak, aby walidacja serwera i klienta mogła zostać maksymalnie zintegrowana, aby ograniczyć pracę wymaganą do sprawdzenia poprawności na serwerze i kliencie. Ale bądź pewien, że musisz zrobić jedno i drugie.

Jeśli pomijanie sprawdzania klienta (za pomocą manipulacji DOM) pozwala uniknąć sprawdzania poprawności serwera (co, jak się wydaje, wskazuje), oznacza to, że sprawdzenie poprawności serwera dla tego wystąpienia może nie być odpowiednio stosowane. Powinieneś ponownie wywołać weryfikację serwera w akcjach kontrolera lub w warstwie usług. Scenariusz, który opisujesz, nie powinien podważać twojego sprawdzania poprawności serwera.

W opisanym scenariuszu metoda atrybutów DataAnnotation powinna wystarczyć. Wygląda na to, że wystarczy wprowadzić kilka zmian w kodzie, aby upewnić się, że sprawdzanie poprawności serwera jest wywoływane również podczas przesyłania formularza.

2

The DataAnnotation z pewnością nie wystarczy. Używam go również do wstępnej weryfikacji moich połączeń z modelem domeny, aby uzyskać lepsze raportowanie błędów i jak najwcześniej zakończyć się niepowodzeniem.

Można jednak zmodyfikować model samej DataAnnotation, aby upewnić się, że właściwości z [Wymagane] MUSZĄ być wysłane. (zajmie się później kodem).

UPDATE Pobierz źródło DataAnnotations modelu Binder i znaleźć ten wiersz w DataAnnotationsModelBinder.cs

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

go zmienić na

// 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)) { 
+0

Dzięki Martijn. Czekam na Twój kod. –

+0

Oczywiście, opublikowałem to przed wyjściem do pracy (w pracy nadal), więc nie ma czasu na kodowanie :(. Zmodyfikowaliśmy spoiwo zanim nieco, ponieważ nie sprawdziłem zagnieżdżonych obiektów i zresetowałem nieprawidłowe właściwości do wartości null, które nie zgadzałem się z patrz http://stackoverflow.com/questions/820468/how-does-dataannotationsmodelbinder-work-with-custom-viewmodels/864541#864541 Od tego czasu dodałem wymagane kontrole, ale chciałbym je przetestować, gdy wrócę do domu przed –

+0

Zaktualizowany za pomocą kodu, ale nie jestem w stanie go przetestować poprawnie, zrobi to ponownie jutro, ale opublikuje go, więc być może możesz go ocenić szybciej, przechodzi testy jednostkowe projektu, ale żeby być uczciwym to nie testowanie tego przypadku: D –

7

Połączyłem xVal z DataAnnotations i napisałem własny filtr działania, który sprawdza parametry dowolnego elementu dla celów weryfikacji. Tak więc, jeśli brakuje jakiegoś pola w poczcie zwrotnej, ten walidator wypełni słownik ModelState, co spowoduje, że model będzie nieprawidłowy.

Wymagania:

  • moja jednostka/modelu obiektów wszystkie implementują interfejs, który deklaruje IObjectValidatorValidate() metody.
  • moja klasa atrybut nazywa ValidateBusinessObjectAttribute
  • poprawności xVal biblioteka

kod filtr Działanie:

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); 
      } 
     } 
    } 
} 

mojego działania kontrolera jest zdefiniowana tak wtedy:

[ValidateBusinessObject] 
public ActionResult Register(User user, Company company, RegistrationData registrationData) 
{ 
    if (!this.ModelState.IsValid) 
    { 
     return View(); 
    } 
    ... 
} 
+0

Czy masz bardziej szczegółowy przykład, jak korzystać z tego lub projektu do pobrania prawdopodobnie –

+0

@geocine: Gdzie wydaje się być problem? Czy używasz MVC1? Nowsze wersje nie wymagają tego, ponieważ automatycznie sprawdzają poprawne parametry typów ... Ale ten przykład jest tutaj tak szczegółowy, jak powinien być w rzeczywistości. Więc gdzie wydaje się być problem? –

+0

Po prostu przeszedł i jestem nowy w aspmvc czytania o problemach z walidacją. Zapomniałem, że używam MVC 2. moje złe. –

2

Pisałem mój własny ValidationService dla MVC 1.0 przez kopiowanie wzorców z obu xV Dane użytkownika DataAnnotationsRuleProvider i DataAnnotationsModelBinder firmy Microsoft (oraz komentarze Martijn). Interfejs usługi jest poniżej:

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); 
} 

Usługa jest biegaczem walidacja że spacery drzewo właściwością instancji obiektu otrzymuje i faktycznie wykonuje atrybuty walidacja, że ​​znajdzie się na każdej nieruchomości, budując listę obiektów ErrorInfo kiedy atrybuty są nieprawidłowe. (Opublikuję całe źródło, ale zostało napisane dla klienta i nie wiem jeszcze, czy jestem do tego upoważniony.)

Możesz wtedy mieć swoje kontrolery, usługi logiki biznesowej jawnie wywoływać sprawdzanie poprawności, gdy jesteś gotowy, zamiast polegać wyłącznie na modelowym segregatorze do sprawdzania poprawności.

Istnieje kilka innych pułapek, które powinny być świadomy:

  • domyślnej DataTypeAttribute w danych adnotacje w rzeczywistości nie robić żadnych walidację typu danych, więc trzeba napisać nowy atrybut, który faktycznie wykorzystuje wyrażenia regularne XVal (lub coś innego) do wykonuje walidację danych po stronie serwera sprawdzania poprawności.
  • xVal nie chodzić właściwości, aby utworzyć po stronie klienta walidacji, więc może chcesz, aby jakieś tam zmiany, aby uzyskać bardziej niezawodne walidacji po stronie klienta.

Jeśli mam pozwolenie i mam czas, postaram się udostępnić więcej źródeł ...

1

See codeproject Server-side Input Validation using Data Annotations

sprawdzania poprawności danych wejściowych może odbywać się automatycznie po stronie klienta w ASP.NET MVC lub jawnie aktualizacji modelu wbrew zasadom. Ta końcówka opisuje, jak można to zrobić ręcznie po stronie serwera aplikacji ASP.NET lub w kodzie repozytorium aplikacji 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); 
Powiązane problemy