Sto facendo una serie di indagini per la stesura di un progetto di un sito web e valutando le tecnologie da adottare. E così ecco questo post, che è solo una trascrizione dei miei pensieri.
A parte una serie di piccole scocciature che credo presto verranno colmate, Asp.net MVC 3 è decisamente maturo.
Mi manca molto una formalizzazione più evidente del concetto di ViewModel che non solo casca a fagiolo in asp.net mvc ma è, a mio avviso, un passo irrinunciabile per creare una applicazione che abbia un ciclo di vita gestibile. Tutto facilmente sopperibile ma visto che il wizard di vs.net guida ad uno sviluppo molto più pattern-oriented rispetto a tutti gli altri wizard di vs.net, la formalizzazione del viewmodel la sento proprio come una vera e propria mancanza. Probabilmente il wizard più pattern-oriented dopo mvc è quello della document-view di VC++.
Facendo una piccola digressione viene da chiedersi perché asp.net goda del privilegio di un wizard che sposa un pattern, mentre WPF invece sia lasciato totalmente libero, laddove MVVM è a mio avviso irrinunciabile per qualsiasi cosa vada oltre la mera demo. Ma qui uscirei OT rispetto al titolo del post.
MVC è una tecnologia nata per un web di nuova generazione. MVC oggi ha senso (e a mio avviso non lo avrebbe avuto 10 anni fa) per una serie di motivi:
- i postback perché abbruttiscono l'esperienza utente
- tanto scripting perché i browser di oggi sono più potenti
- tanto scripting perché jQuery funziona egregiamente
- tanto scripting perché i browser aderiscono agli standard molto più di prima
- il dev vuole più controllo sull'html
- le architetture e le tecnologie service-oriented favoriscono/semplificano l'uso di chiamate ajax-like
Detto questo nascono però tutta una serie di problematiche relative alla sicurezza come gli attacchi di Cross-Site Request Forgery (CSRF) che consistono nel validare che una richiesta (tipicamente una POST) provenga dal dominio corretto. Per esempio se un sito di hacking che state inavvertitamente visitando vi fa eseguire una POST Ajax con l'ordine di esecuzione di un bonifico, è sperabile che qualcuno si sia posto il problema e la blocchi .
MVC ha built-in un sistema di anti-CSRF, l'attributo ValidateAntiForgeryToken, che consente di evitare che questo accada. Stupisce un po' leggere che uno dei suoi padri, Phill Haack, dica: “we haven’t run extensive security analysis on our approach” a questo link:
http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-%20aspnet-mvcs-antiforgerytoken-helper/
A parte questo, il meccanismo è valido se si scambia XML ma appare inusabile con formato Json, altrimenti si perde il mapping dei dati postati sul model, caratteristica molto comoda in MVC3.
D'altra parte se i dati sono Json il meccanismo di validazione è in teoria inutile, visto che i post Json cross-domain sono disabilitati da parte di tutti i maggiori browser. Un layer addizionale di sicurezza certamente non guastava, ma questo è quanto sia disponibile oggi in MVC3.
E allora veniamo al dunque. Siamo sicuri che quello sia l'unico problema di sicurezza in una tecnologia che fa di json, ajax etc. uno degli aspetti chiave?
Possiamo identificare diversi altri punti:
- Evitare post multipli (per esempio in un meccanismo di voting)
- Permettere un numero massimo di post (simile al precedente ma con un numero di post >=1 e <n)
- Permettere un numero di post pari al numero di get. Cioè puoi sottomettere un risultato ma solo ad ogni refresh (GET) di quella pagina (questo evita le post da pagine che non sono inerenti o addirittura di un altro dominio)
- …
Da notare che i problemi di cui sopra devono essere risolti anche in assenza di autenticazione di un utente. Posso anche volere il voto di qualcuno senza necessariamente autenticarlo. Certo, l'utente può barare aprendo un altro browser, cancellando i cookie, chiudendo il browser, etc. Ma esistono una serie di casistiche in cui questo tipo di casi sono accettabili (come avviene su un voting su larga scala).
Tipicamente questo tipo di problemi fanno uso di token e/o hash, cioè dati crittografati che contengono le informazioni come data/ora della richiesta, numero di post, etc.
Se voglio scalare, questo token dovrebbe essere messo in un campo hidden sul browser anziché sul server … ma il ViewState non c'è più (o meglio c'è ancora ma è in pratica inutilizzabile). Non parlo di ViewState per i controlli, ma di un "blob" minimale di dati criptati che faccio custodire al browser invece di intoppare il server.
A quanto ho capito non ci sono soluzioni built-in ma quando si sceglie una tecnologia, in questo casi MVC, queste sono cose da sviluppare e hanno un costo di cui dovrò tenere conto. Mi meraviglio che non siano popolari come mi sarei aspettato.