C'è qualche ragione per non passare direttamente dal Javascript lato client a un database?

60

Quindi, diciamo che costruirò un clone di Stack Exchange e deciderò di usare qualcosa come CouchDB come mio backend store. Se utilizzo l'autenticazione integrata e l'autorizzazione a livello di database, c'è qualche ragione per non permettere al Javascript lato client di scrivere direttamente sul server CouchDB disponibile pubblicamente? Poiché si tratta fondamentalmente di un'applicazione CRUD e la logica aziendale è costituita da "Solo l'autore può modificare il proprio post", non vedo la necessità di disporre di un livello tra il lato client e il database. Utilizzerei semplicemente la convalida sul lato CouchDB per assicurarmi che qualcuno non inserisca i dati inutili e si assicuri che le autorizzazioni siano impostate correttamente in modo che gli utenti possano solo leggere i propri dati _user. Il rendering verrà eseguito sul lato client da qualcosa come AngularJS. In sostanza potresti avere solo un server CouchDB e un sacco di pagine "statiche" e sei a posto. Non avresti bisogno di alcun tipo di elaborazione lato server, solo qualcosa che potrebbe servire le pagine HTML.

Aprire il mio database fino al mondo sembra sbagliato, ma in questo scenario non riesco a pensare al motivo per cui finché le autorizzazioni sono impostate correttamente. Va contro il mio istinto come sviluppatore web, ma non riesco a pensare ad una buona ragione. Quindi, perché questa è una cattiva idea?

EDIT: Sembra che ci sia una discussione simile qui: Scrivere Web "server less" applicazioni

EDIT: discussione eccezionale finora e apprezzo il feedback di tutti! Sento che dovrei aggiungere alcune ipotesi generiche invece di chiamare CouchDB e AngularJS in modo specifico. Quindi supponiamo che:

  • Il database può autenticare gli utenti direttamente dal suo negozio nascosto
  • Tutte le comunicazioni del database avverrebbero su SSL
  • La convalida dei dati può (ma forse non dovrebbe?) essere gestita dal database
  • L'unica autorizzazione che ci interessa oltre alle funzioni di amministrazione è la possibilità solo a qualcuno di modificare il proprio post
  • Siamo perfettamente a posto con chiunque sia in grado di leggere tutti i dati (TRANNE i record dell'utente che potrebbero contenere hash delle password)
  • Le funzioni amministrative sarebbero limitate dall'autorizzazione del database
  • Nessuno può aggiungersi a un ruolo di amministratore
  • Il database è relativamente facile da ridimensionare
  • C'è poca o nessuna vera logica aziendale; questa è un'app CRUD di base
posta Chris Smith 19.12.2012 - 15:34
fonte

15 risposte

47

Come suggerisci, crea un accoppiamento stretto tra la tua lingua lato client e il tuo database.

Può andar bene - c'è meno codice da scrivere e mantenere, e in teoria il debug potrebbe / dovrebbe andare un po 'più veloce.

D'altro canto, rende altri aspetti più difficili. Se / quando hai bisogno di cambiare una di queste tecnologie, avrai un momento più difficile a causa dello stretto accoppiamento tra loro.

Proteggersi dagli attacchi sarà (abbastanza) un po 'più difficile. Si presume che il client presenterà sempre richieste ben formattate nel database. Ciò presuppone che nessuno possa hackerare il codice lato client per inserire istruzioni dannose. In altre parole, "prenderanno in prestito" i meccanismi di autenticazione e sostituiranno il normale codice cliente con il loro.

Non lo consiglierei e molti direbbero con veemenza di non farlo. Ma può essere fatto.

    
risposta data 19.12.2012 - 15:54
fonte
36

Probabilmente non è una grande idea. E il primo e più strong motivo che posso dare è che un server di database non è progettato per essere un server web pubblico. Al contrario, la saggezza convenzionale dice che dovresti nascondere il tuo database dietro un firewall.

Se hai bisogno di prove a sostegno, ci sono molte preoccupazioni - non tutte insormontabili, ma molte cose a cui pensare. In nessun ordine particolare, eccone alcuni:

  • Non può eseguire la sanitizzazione delle query, perché le stai inviando direttamente .
  • Le autorizzazioni del database tendono a funzionare in modo diverso rispetto alle autorizzazioni del server Web e dell'applicazione. I server Web e le strutture delle applicazioni non ti generano nulla e devi creare ed esporre esplicitamente le risorse, gli endpoint e le azioni individuali. I database, d'altra parte, ti chiedono di assegnare ruoli ad alto livello.
  • Probabilmente non è ottimizzato per sostenere il carico di lavoro di un server web; non puoi beneficiare del pool di connessioni.
  • I server web più popolari sono stati suddivisi in molto . E hanno ricevuto molte patch di sicurezza. Il tuo DBMS è stato fondamentalmente progettato per nascondersi dietro un firewall, quindi probabilmente non è stato testato nemmeno una frazione della percentuale delle potenziali minacce che si troveranno ad affrontare sul web pubblico.
  • Tu devi utilizzare il linguaggio di query del database per proteggere i dati privati. A seconda del tuo DBMS, può essere difficile.
  • Tu devi utilizzare il linguaggio di query del database per filtrare insiemi di dati di grandi dimensioni, cosa che potresti comunque cercare di fare; ma qualcosa che può diventare gravoso per regole aziendali più complicate.
  • Supporto limitato o assente per le librerie di terze parti.
  • Supporto della community molto limitato (potenzialmente zero) per molti dei problemi che incontrerai.

... E sono sicuro che ci siano altre preoccupazioni. E sono sicuro che ci sia una soluzione per la maggior parte - se non tutte queste preoccupazioni. Ma c'è una lista per iniziare!

    
risposta data 19.02.2016 - 23:20
fonte
16

Il miglior singolo motivo che posso immaginare è: perché questo metodo non è direttamente supportato o raccomandato da alcuna parte coinvolta.

I fornitori di browser, gli standard EcmaScript, gli sviluppatori di sistemi di database, le società di apparecchiature di rete, gli architetti di hosting / infrastruttura e gli esperti di sicurezza non supportano attivamente (o forse considerano) il caso d'uso proposto. Questo è un problema, perché il tuo metodo proposto richiede a tutte queste entità - e non solo - di lavorare in modo appropriato per la tua applicazione, anche se nessuno dei sistemi coinvolti è stato progettato per supportarlo.

Non sto dicendo che non è possibile. Sto solo dicendo che è meno come "re-inventare la ruota" e più come reinventare l'interazione client-server basata su browser.

Nel migliore dei casi, farai un sacco di lavoro per far funzionare i sistemi al livello più semplice possibile. I moderni database popolari non sono RESTful o costruiti per funzionare su HTTP, quindi creerai i tuoi driver client basati su WebSocket (presumo).

Anche se riesci a far funzionare tutto tecnicamente, rinuncerai a molte delle più potenti funzionalità delle architetture moderne. Non avrai alcuna difesa approfondita - tutti potranno facilmente connettersi direttamente all'obiettivo principale della maggior parte dei tentativi di hacking del sito web. Ma lo scenario che proponi è molto, molto peggio di quello.

Il modello proposto non espone semplicemente il server, ma espone stringhe di connessione valide. Gli aggressori non possono semplicemente eseguire il ping del server: possono effettuare il login e alimentarlo attivamente con i comandi. Anche se è possibile limitare l'accesso ai dati, non sono a conoscenza di strumenti sufficienti nei sistemi DBMS per proteggere dagli scenari di tipo Denial of Service e il loro tipo. Quando si lavora in versioni avanzate di SQL, come TSQL, è spesso banalmente facile produrre bombe che funzionano in modo efficace all'infinito (alcuni join senza restrizioni per produrre un prodotto cartesiano e si avrà un SELECT che girerà per sempre, facendo un lavoro pesante) . Immagino che avresti bisogno di disabilitare la maggior parte delle funzionalità di SQL, eliminando anche le query SELECT di base con JOIN e forse permetti solo di chiamare stored procedure? Non so nemmeno se puoi farlo, non mi è mai stato chiesto di provarci. Non suona bene.

La scalabilità del database tende anche ad essere uno dei problemi più difficili nel lavorare su grandi scale, mentre il ridimensionamento di più server HTTP, specialmente con pagine statiche o memorizzate nella cache, è una delle parti più semplici. La tua proposta rende il database più funzionale essendo responsabile per il 100% delle attività lato server. Questo è un difetto killer tutto da solo. Ciò che guadagni dallo spostamento del lavoro sul cliente che perdi spostando più lavoro sul database.

Infine, vorrei solo sottolineare che il cuore di ciò che proponi non è nuovo, ma in realtà risale a decenni. Questo modello è chiamato il modello "Fat Database", che sostanzialmente ha spostato la maggior parte della logica lato server nel database proprio come si propone. Ci sono molte ragioni per cui il modello è andato via su Internet di massa, e sarebbe probabilmente informativo approfondire la storia da solo. Si noti inoltre che anche in questo caso si è tenuto in scarsa considerazione il fatto di avere utenti completamente non fidati in grado di accedere al sistema ed eseguire comandi, in quanto l'accesso sarebbe comunque controllato per selezionare gli utenti interni (noti) che non avrebbero dovuto attaccare costantemente il sistema. / p>

Il fatto è che avrai ancora bisogno di un server HTTP per servire i file, dato che i sistemi di database semplicemente non lo fanno. Allo stesso tempo, tutto ciò che si propone può essere ottenuto utilizzando un modello thin server (come con Nodejs) per esporre un'interfaccia RESTful al proprio database. Questo è popolare per un motivo: funziona, mantiene il database nascosto dietro strati di protezione, è estremamente scalabile e tuttavia ti consente di costruire il tuo database come spesso o sottile come ti interessi.

    
risposta data 20.02.2016 - 00:14
fonte
8

Since this is basically a CRUD application and the business logic consists of "Only the author can edit their post" I don't see much of a need to have a layer between the client-side stuff and the database. I would simply use validation on the CouchDB side to make sure someone isn't putting in garbage data and make sure that permissions are set properly so that users can only read their own _user data.

Bene, posizionando la tua autorizzazione (i problemi di sicurezza) e la convalida logica dal database offre una separazione delle preoccupazioni nel tuo sistema software. Così puoi testare, mantenere, ridimensionare e riutilizzare i tuoi blocchi di codice logici con meno rischi di frenare la funzionalità del sistema.

Fornire capacità per l'input del client di comunicare direttamente con il database ha un potenziale enorme di rovinare i dati .

Questo significa anche che evitare / rimuovere accoppiamento stretto rende il tuo sistema software più manutenibile e SOLID.

    
risposta data 19.12.2012 - 15:54
fonte
6

Lasciando che l'utente interagisca con il database sembra davvero pericoloso per me.

Il meccanismo di autenticazione di CouchDB è davvero così sofisticato che puoi isolare l'accesso in lettura e scrittura di un utente solo ai dati che si suppone di leggere e scrivere (stiamo parlando di documenti, forse anche per documento -il privilegio di accesso qui)? Che dire dei dati "comuni" condivisi da più utenti? Non esiste affatto nella progettazione della tua applicazione?

Vuoi veramente che l'utente sia in grado di cambiare i suoi dati in QUALSIASI modo? Che dire delle iniezioni XSS, per esempio? Non sarebbe meglio avere un livello server per filtrare quelli prima che entrino nel database?

    
risposta data 19.12.2012 - 17:39
fonte
6

Hai ottenuto una serie di motivi, ma eccone uno: l'impermeabilità futura. Prima o poi, man mano che la tua applicazione si evolverà, ti verranno presentati alcuni requisiti che non possono essere raggiunti facilmente o in sicurezza nel JS lato client o come stored procedure nel tuo database.

Ad esempio, ti viene detto che tutte le nuove registrazioni devono avere una verifica CAPTCHA valida. Questo sarebbe davvero abbastanza facile con praticamente qualsiasi moderno framework per applicazioni web. Basta schiaffare un reCAPTCHA sul modulo di registrazione, passare il token di risposta di reCAPTCHA al back-end e aggiungere un paio di linee di codice al tuo backend per verificare la validità del token con l'API di Google (o meglio ancora, usa una libreria che qualcun altro ha scritto per farlo per te).

Se stai usando un sistema a due livelli e ti affidi al database per tutta la tua logica lato server, come procederai a verificare il token? Sì, suppongo che potrebbe essere teoricamente possibile, a seconda del DBMS, scrivere una stored procedure che in qualche modo chiama una shell e invoca l'arricciatura con gli argomenti appropriati. Questa è anche quasi certamente un'idea orribile: il filtraggio degli input e la protezione dalle vulnerabilità della sicurezza sarebbero terribili; avresti un problema con la gestione degli errori e i timeout; e tu dovresti analizzare la risposta da solo. Per non parlare del fatto che un DBMS non è destinato a fare questo, quindi non c'è motivo di pensare che le prestazioni, la stabilità, la sicurezza dei thread, ecc ... non saranno problemi. Vedi, ad esempio, questo thread , che discute alcuni di questi problemi per Postgres.

E questo è solo il problema relativo all'aggiunta di un semplice CAPTCHA a un modulo. Che cosa hai intenzione di fare se desideri aggiungere la verifica SMS o un processo in background che invii email agli utenti inattivi per ricordare loro la tua app o aggiungere una funzione di caricamento file in modo che le persone possano impostare un'immagine del profilo? Forse decidi che la tua applicazione dovrebbe avere qualche test automatico un giorno? O vuoi tenere traccia delle modifiche alle tue procedure in un sistema di controllo delle versioni? Esistono numerose librerie e strumenti per la maggior parte delle lingue utili per gestire la maggior parte di questi compiti, ma pochi per nessuno saranno disponibili per il tuo DBMS, perché non è pensato per farlo.

Alla fine, vorrai fare qualcosa che non puoi ragionevolmente fare direttamente nel tuo DBMS, e poi rimarrai bloccato. Poiché avrai creato l'intera applicazione nel tuo DBMS, non avrai altra alternativa se non quella di ottenere un server web e iniziare a ricostruire i pezzi in un'altra lingua, solo per aggiungere una semplice funzionalità.

E sarebbe un vero peccato, perché abbiamo già un nome per il luogo in cui si inserisce la logica dell'applicazione, e per un motivo è chiamato "codice sorgente dell'applicazione" piuttosto che "stored procedure del database".

    
risposta data 20.02.2016 - 05:11
fonte
5

Se i tuoi controlli di sicurezza e la logica di business sono contenuti nel tuo javascript lato client, possono essere sostituiti da un utente malintenzionato. In alternativa, puoi sfruttare una tecnologia basata sul server basata su JavaScript (come Node.JS ) per gestire convalida, autorizzazione e simili.

    
risposta data 19.12.2012 - 16:24
fonte
2

Qualsiasi vincolo aziendale che potresti voler garantire dovrebbe essere lato server validato. Anche se controlli l'accesso degli utenti, qualcuno potrebbe inviare dati non validi.

Seguendo il tuo esempio di clone di stackoverflow:

  • In che modo bloccheresti comunque le domande "chiuse" sul sito?
  • Come impedirebbe alle persone di eliminare i commenti?
  • Come impedirebbe alle persone di falsificare le date dei commenti?
  • Come impedirebbe agli utenti di effettuare l'upvoting di 50 volte lo stesso post?
  • Probabilmente ci sono molti più esempi se riesci a scavare un po 'di più.

Ognuno può manipolare il codice lato client e violare completamente l'integrità dei dati (anche se limitato a determinati oggetti, come i propri messaggi).

    
risposta data 20.12.2012 - 06:33
fonte
1

Modifica la pagina in firebug e ad un certo punto metti una riga simile a questa:

ExecDbCommand("DROP TABLE Users")

Esegui.

Modifica:

La domanda riguardava infatti CounchDB, quindi non è stato necessario eseguire SQL qui. Eppure l'idea è la stessa. Presumo che qualsiasi applicazione non banale dipenda dai dati per rispettare alcune regole di coerenza che vengono controllate / applicate dal codice dell'applicazione. Un utente malintenzionato può modificare il codice client per salvare i dati in un modulo che viola le regole aziendali e potrebbe causare il caos nella tua applicazione.

Se il tuo sito considera tutti i possibili stati di dati validi dal punto di vista del business, allora segui questo percorso, ma se questo non è il tuo caso (probabile), allora vorrai avere la garanzia che tutti i dati che vengono memorizzati siano generato da tuo codice e in base a tue regole .

    
risposta data 19.12.2012 - 17:39
fonte
1

Vecchia domanda, lo so, ma volevo farlo perché la mia esperienza è molto diversa dalle altre risposte.

Ho trascorso molti anni a scrivere applicazioni collaborative in tempo reale. L'approccio generale per queste applicazioni consiste nel replicare localmente i dati e sincronizzare le modifiche con i peer il più velocemente possibile. Tutte le operazioni sui dati sono locali, quindi tutta la memorizzazione dei dati, l'accesso ai dati, la logica aziendale e l'interfaccia utente sono dei livelli locali. Il movimento "offline first" ( link ) ha adottato questo approccio per la creazione di applicazioni Web offline e potrebbe avere alcune risorse pertinenti. Questi tipi di casi d'uso non impongono solo l'apertura del livello di accesso ai dati ai client, ma anche l'archiviazione dei dati! Lo so, lo so. Sembra pazzo, vero?

Le preoccupazioni per queste app offline sono simili a quelle che hai chiesto, solo un livello rimosso. Mi sembra rilevante. Dato che stai aprendo l'accesso diretto ai dati ai clienti, la domanda diventa, come puoi limitare gli effetti di un utente malintenzionato? Bene, ci sono molte strategie, ma non sono ovvie se provi da un background di sviluppo più tradizionale.

Il primo malinteso è che esporre il database significa esporre tutti i dati. Prendi CouchDB per esempio; i database in CouchDB sono leggeri, quindi non ci si potrebbe ripensare alla creazione di centinaia di migliaia di database separati su un server. Gli utenti possono accedere solo ai database a cui viene concessa l'autorizzazione ad accedere come lettori o scrittori (per non parlare delle funzionalità di convalida e cosa non di CouchDB), in modo che possano accedere solo a un sottoinsieme di dati.

Il secondo malinteso è che un utente che batta i dati è un problema! Se agli utenti viene fornita una replica di un database, possono cazzare tutto ciò che vogliono senza influire sugli altri utenti. Tuttavia, è necessario convalidare le modifiche prima di replicare i dati nell'archivio "centrale". Pensa a Git: gli utenti possono fare ciò che vogliono in rami, fork e repository locali senza intaccare il ramo principale. Riunire per padroneggiare comporta molte cerimonie e non è fatto alla cieca.

Sto costruendo un sistema che utilizza CouchDB in cui gli utenti devono collaborare ai dati per creare un set di dati che viene poi "pubblicato" tramite un flusso di lavoro QA / QC. La collaborazione viene eseguita su una replica dei dati (che chiamiamo staging o database funzionante) e una volta completata, una persona responsabile esegue QA / QC sui dati e solo dopo viene replicata nel repository principale.

Da questo traggono molti benefici che sono difficili da ottenere in altri sistemi - come il controllo delle versioni, la replica e la collaborazione (lasciati lavorare offline!) per le tradizionali applicazioni CRUD a tre livelli è super difficile.

Il mio consiglio: se la tua domanda è "tradizionale", fallo nel modo tradizionale. Se una delle cose di cui ho parlato sopra (anche se c'è molto di più ...) si applica a te, quindi considera le architetture alternative e preparati a pensare lateralmente.

    
risposta data 30.08.2018 - 04:40
fonte
0

Penso che, date tutte le tue ipotesi, sia fattibile passare direttamente dal client al database. Tuttavia, è ragionevole verificare se le ipotesi sono valide e probabilmente rimarranno tali anche in futuro.

Sarei preoccupato che in futuro potrebbe non essere corretto per tutti leggere tutti i dati, e soprattutto che potrebbe sviluppare più logica di business in futuro. Entrambi sono più probabili se il progetto ha successo.

Finché ti lasci un modo per affrontare questi problemi in futuro, quando e se effettivamente dovessi occupartene, penso che il tuo progetto funzionerà. Penso che dovrai fare molta attenzione a separare le preoccupazioni nel codice JavaScript, e alcune potrebbero finire per essere riscritte sul server in un secondo momento.

Ma potrei sicuramente vedere dove potrebbe valere la pena rischiare di farlo più tardi rispetto al vantaggio di un minor numero di parti mobili oggi.

    
risposta data 19.12.2012 - 19:14
fonte
0

Prima di tutto grazie per la domanda FUORI PORTA ....:)

Ma quello che vorrei suggerire è; Cerca sempre di mantenere una separazione tra i tuoi 3 livelli. che sono Presentazione / Business e Database o DAO perché sarà la migliore pratica in quei tipi di requisiti e configurazioni in cui ci saranno molte modifiche ogni giorno.

In mondi semplici il tuo livello Presentazione non dovrebbe conoscere il livello Database, ad esempio il formato di alcuni campi di tipo data potrebbe essere diverso dal livello di presentazione e dal livello database in modo che l'utente possa avere la libertà di selezionare il formato adatto della data come per ha bisogno.

E Business Logic deve comportarsi come un accoppiamento tra il livello di presentazione e il livello database / Dao come la fusione dei campi, alcune convalide aziendali, ecc. devono essere gestiti su Business Layer piuttosto che nella sezione Javascript come da domanda.

Questa separazione ti fornirà grande facilità e comportamento durante scenari complessi, funzionalità e persino convalide complesse. Il miglior vantaggio è: puoi avere diverse tecnologie per implementare questi livelli e possono essere modificati in base alle esigenze o all'ambito aziendale.

Grazie

    
risposta data 20.12.2012 - 06:16
fonte
0

Se desideri creare SQL in JavaScript e inviarlo al database, che verifica i diritti, ecc., anziché da motivi di sicurezza, sarebbe un disastro. Semplicemente perché quando costruisci un'API e compilare le query manualmente, è necessario analizzare dal punto di vista della sicurezza solo il numero limitato di query. Se le query sono costruite al di fuori del tuo sistema, hai potenzialmente un numero illimitato di trucchi che qualcuno potrebbe fare.

Ma non è il caso dato che stai usando un database di valori-chiave (per quanto sia comprensibile, CouchDB rientra generalmente in quella categoria). L'interfaccia di database stessa è una sorta di livello intermedio, ed è stata testata per ragioni di sicurezza dal team di Apache. A causa dell'API JavaScript relativamente semplice, questo è ancora più facile da analizzare per potenziali difetti rispetto a tali complicate interfacce che hanno le applicazioni JSF.

Questa può essere una soluzione sicura, se si eseguono test di sicurezza complessi. Questo può essere ancora più semplice quando si utilizzano framework come JSF, che spesso utilizzano API poco leggibili. La sicurezza dall'oscurità non è considerata una soluzione.

In relazione alla tua domanda, non sarà comunque l'accesso diretto al database. L'accesso diretto sarebbe la query SQL di costruzione in JavaScript (purtroppo, ho visto tali soluzioni). Nel tuo caso il CouchDB stesso fornisce il livello di isolamento. Ovviamente puoi avvolgerlo nella tua API per renderlo più duro, ma finché puoi testare facilmente cosa può fare un determinato utente e se i vincoli di sicurezza funzionano, avrai una soluzione sicura e affidabile senza livelli aggiuntivi.

    
risposta data 19.12.2012 - 19:46
fonte
0

Vedo due problemi:

1. Accoppiamento stretto: modifica l'opzione DB? Bene, ora devi anche cambiare tutto il tuo codice lato client. Fidati di me. Non abbiamo bisogno di più problemi sul lato client.

2. TMI Security Issue: rivela troppo su come funziona la roba. L'autenticazione potrebbe essere ancora un ostacolo, ma trovare un exploit è molto più facile quando sai esattamente cosa succede sul lato server.

Un livello medio molto sottilissimo potrebbe essere un modo migliore per andare.

    
risposta data 20.12.2012 - 08:49
fonte
-1

Il tuo client non può usare la tua app Web se javascript è disabilitato (o non è supportato nel browser del suo dispositivo) se javascript è l'unico livello di accesso al database.

    
risposta data 19.12.2012 - 16:10
fonte

Leggi altre domande sui tag