Sicurezza J2EE: contenitore contro personalizzato

Sin dalla prima volta che una pagina di accesso è stata aggiunta a un'applicazione Web, la sicurezza è sempre stata uno dei componenti chiave per il successo delle applicazioni sul Web. Storicamente, tutto è stato codificato a mano. Ogni applicazione Web aveva un metodo personalizzato per autenticare e quindi autorizzare gli utenti. Gli sviluppatori hanno anche integrato componenti per la registrazione, l'amministrazione e qualsiasi altra funzione necessaria. Sebbene un bel po 'di overhead, questo approccio ha consentito una grande flessibilità.

Con l'avvento di JAAS, il servizio di autenticazione e autorizzazione Java, le applicazioni hanno acquisito una serie di interfacce e una configurazione che potevano sfruttare per standardizzare tali attività. Anche con l'aggiunta di JAAS alla specifica, J2EE ha ancora alcuni problemi da risolvere prima che gli sviluppatori di applicazioni possano interrompere la creazione di API personalizzate. Scegliere tra l'utilizzo degli standard J2EE o la creazione di una soluzione personalizzata richiede la conoscenza dei compromessi di ciascuno e, ovviamente, dei requisiti dell'applicazione.

Questo articolo si propone di fornire tutte le informazioni necessarie per decidere tra sicurezza personalizzata o container. Discuto le funzioni di sicurezza delle applicazioni più comuni per fornire il background necessario sulla sicurezza. Di seguito a questa discussione viene fornita una spiegazione dettagliata delle implementazioni della sicurezza J2EE fornite dalle specifiche nonché dei metodi più comuni di implementazione della sicurezza personalizzata. Dopo aver compreso meglio ciascuno dei metodi, è necessario disporre di informazioni sufficienti per scegliere quale metodo si adatta meglio ai requisiti dell'applicazione.

Cos'è un container?

Prima di discutere i diversi tipi di sicurezza e i problemi di implementazione della sicurezza, esaminiamo cos'è un contenitoreè. Un contenitore è un ambiente in cui viene eseguita un'applicazione. È anche sinonimo di application server J2EE. In termini di contenitori J2EE, all'interno del contenitore viene eseguita un'applicazione J2EE, che ha responsabilità specifiche rispetto all'applicazione. Esistono molti tipi diversi di contenitori J2EE e diversi livelli di supporto J2EE. Tomcat di Apache è un contenitore Web che implementa solo le porzioni Servlet (applicazione Web) della specifica J2EE. WebLogic di BEA è un application server J2EE completamente conforme, il che significa che supporta tutti gli aspetti della specifica J2EE e ha superato i test di certificazione J2EE di Sun. Se non si è sicuri del supporto fornito dal server delle applicazioni, contattare il fornitore per ulteriori informazioni.

Sicurezza delle applicazioni

Un altro argomento che dobbiamo trattare prima di iniziare è la distinzione tra sicurezza delle applicazioni e altri tipi di sicurezza. La sicurezza dell'applicazione è la sicurezza eseguita direttamente da un'applicazione o indirettamente da un framework o contenitore per un'applicazione rispetto agli utenti di tale applicazione. Un esempio di utente dell'applicazione è qualcuno che accede a una libreria in linea e acquista alcuni libri Java. Esistono altri tipi di sicurezza, come la sicurezza di rete e la sicurezza JVM. Un esempio di questi tipi di sicurezza è l'utente che avvia un processo Java su una macchina. In tutto il resto di questo articolo, ogni volta che parlo di sicurezza, intendo la sicurezza delle applicazioni. Gli altri tipi di protezione non rientrano nell'ambito di questa discussione.

Il focus qui è specificamente la sicurezza J2EE, che è un tipo di sicurezza dell'applicazione perché si occupa degli utenti di un'applicazione J2EE (cioè, chiamanti). Un utente potrebbe essere qualcuno che utilizza la libreria in linea o un'altra applicazione che utilizza i servizi di acquisto dell'applicazione libreria, come un altro rivenditore in linea.

Funzioni di sicurezza delle applicazioni

Esistono cinque funzioni principali quando si considera la sicurezza dell'applicazione: autenticazione, autorizzazione, registrazione, manutenzione dell'account (aggiornamenti) e cancellazione / inattivazione dell'account. Sebbene solo un piccolo sottoinsieme di tutte le possibili funzioni che un'applicazione potrebbe avere, queste sono le più fondamentali e abbastanza standard per tutte le applicazioni. Meno formalmente, queste funzioni sono conoscere l'utente (autenticazione), sapere cosa può fare l'utente (autorizzazione), creare nuovi utenti (registrazione), aggiornare le informazioni dell'utente (manutenzione dell'account) e rimuovere un utente o impedire a un utente di accedere all'applicazione (cancellazione dell'account).

La maggior parte delle applicazioni consente all'utente o a un amministratore di eseguire queste funzioni. Quando gli utenti eseguono queste funzioni, lo fanno da soli. Gli amministratori eseguono sempre queste funzioni per conto di altri utenti.

Come verrà illustrato, tutte queste funzioni non possono essere realizzate senza una soluzione personalizzata, anche per l'autenticazione. Esamineremo brevemente ciascuno di essi per illustrare ulteriormente i concetti e ciò che manca a J2EE che deve essere costruito su misura.

Autenticazione

L'autenticazione è il processo di identificazione di un utente che interagisce con un'applicazione. Al momento della stesura di questo documento, l'autenticazione J2EE potrebbe essere implementata utilizzando una varietà di soluzioni, ciascuna definita come parte della specifica J2EE (versione 1.0-1.4). L'autenticazione è il concetto principale di questa discussione e verrà trattata in maggiore dettaglio in seguito. È importante rendersi conto che l'autenticazione è la funzione di sicurezza che ha il maggior supporto all'interno della specifica J2EE, ma di solito è richiesto un codice o una configurazione personalizzati per implementare l'autenticazione J2EE (nota anche come autenticazione del contenitore).

Autorizzazione

L'autorizzazione è il processo di verifica che un utente dispone dell'autorizzazione per eseguire un'azione specifica. J2EE copre questo argomento, ma è vincolato all'autorizzazione basata sui ruoli, il che significa che l'attività può essere limitata in base ai ruoli assegnati all'utente. Ad esempio, gli utenti nel ruolo di manager potrebbero essere in grado di eliminare l'inventario, mentre gli utenti nel ruolo di dipendente potrebbero non farlo.

Inoltre, le applicazioni potrebbero considerare due diversi tipi di autorizzazione: Java Runtime Environment (JRE) / contenitore e autorizzazione dell'applicazione. L'autorizzazione JRE / container è il processo per determinare se l'utente che effettua la richiesta dispone dei privilegi per farlo. Il JRE / contenitore determina ciò prima dell'esecuzione di qualsiasi codice. Un esempio è un contenitore J2EE che deve prima controllare se l'utente corrente dispone delle autorizzazioni per eseguire un servlet (tramite un vincolo dell'URL della risorsa) prima di eseguire il servlet. Questo tipo di autorizzazione è noto anche come sicurezza dichiarativaperché è dichiarato nei file di configurazione per l'applicazione Web. A meno che non sia supportato dal contenitore, la sicurezza dichiarativa non può essere modificata in fase di esecuzione. La sicurezza dichiarativa può essere utilizzata in molti modi per autorizzare gli utenti dell'applicazione J2EE, ma tale argomento esula dall'ambito di questa discussione. (Vedere il Capitolo 12 delle specifiche del servlet 2.3. La sezione 2 copre la sicurezza dichiarativa e 8 è un buon punto di partenza per i vincoli di sicurezza.)

Come accennato in precedenza, l'utente potrebbe essere un'altra applicazione o semplicemente un utente dell'applicazione. In ogni caso, l'autorizzazione JRE / contenitore viene eseguita durante ogni richiesta. Queste richieste potrebbero essere richieste HTTP da un browser a un'applicazione Web o chiamate EJB (Enterprise JavaBeans) remote. In entrambi i casi, a condizione che il JRE / contenitore conosca l'utente, può eseguire l'autorizzazione in base alle informazioni di quell'utente.

L'autorizzazione dell'applicazione è il processo di autorizzazione durante l'esecuzione dell'applicazione. L'autorizzazione dell'applicazione può essere ulteriormente suddivisa in autorizzazione basata sui ruoli e basata sui segmenti. Un esempio di autorizzazione dell'applicazione basata sui ruoli è quando un'applicazione applica diversi livelli di markup in base al fatto che un utente sia un dipendente o un visitatore (ovvero uno sconto per dipendenti). J2EE fornisce API chiamate sicurezza programmatica per ottenere l'autorizzazione basata sui ruoli (vedere il capitolo 12 delle specifiche del servlet 2.3, sezione 3 per ulteriori informazioni).

L'autorizzazione basata su segmenti è un'autorizzazione basata su altri attributi di un utente, come l'età o gli hobby. L'autorizzazione basata su segmenti è chiamata tale perché raggruppa gli utenti in segmenti basati su attributi specifici. J2EE non ha alcun metodo per implementare l'autorizzazione basata sui segmenti. Un esempio di autorizzazione basata su segmenti è se un pulsante su un modulo è visibile agli utenti di età superiore ai 40 anni. Alcuni fornitori possono offrire questo tipo di autorizzazione, ma ciò garantirebbe il blocco del fornitore in tutti i casi.

Registrazione

La registrazione è il processo di aggiunta di un nuovo utente all'applicazione. Gli utenti dell'applicazione potrebbero essere in grado di creare nuovi account per se stessi o l'applicazione potrebbe scegliere di limitare questa attività agli amministratori dell'applicazione. La specifica J2EE non ha un'API o una configurazione che consente alle applicazioni di aggiungere nuovi utenti; pertanto, questo tipo di protezione è sempre personalizzato. J2EE non è in grado di dire al contenitore che un nuovo utente si è registrato e che le sue informazioni devono essere mantenute e mantenute durante la sua sessione.

Manutenzione

La manutenzione dell'account è il processo di modifica delle informazioni sull'account, come le informazioni di contatto, gli accessi o le password. La maggior parte delle applicazioni consente agli utenti dell'applicazione, così come agli amministratori, di eseguire la manutenzione. La specifica J2EE manca anche di un'API o di una configurazione per la manutenzione dell'account. Manca un meccanismo per informare il contenitore che le informazioni sull'utente sono cambiate.

Cancellazione

L'eliminazione dell'account è generalmente limitata solo agli utenti amministratori. In rare occasioni, alcune applicazioni potrebbero consentire agli utenti di eliminare i propri account. La maggior parte delle applicazioni infatti non elimina mai gli utenti; semplicemente disattivano l'account in modo che l'utente non possa più accedere. L'esecuzione di eliminazioni rapide e rapide è generalmente disapprovata perché i dati dell'account sono molto più difficili da resuscitare se necessario. J2EE non fornisce alcun modo per rimuovere o disattivare gli utenti dalle applicazioni. Manca un meccanismo per dire al contenitore che un utente specifico è stato disattivato o rimosso. J2EE non dispone inoltre di un meccanismo per disconnettere immediatamente un utente dall'applicazione quando il suo account è stato eliminato.

Cos'è l'autenticazione del contenitore?

L'autenticazione del contenitore è il processo di comunicazione al contenitore dell'identità dell'utente che effettua la richiesta corrente. Per la maggior parte dei contenitori, questo processo implica l'associazione ServletRequestdell'oggetto corrente , del thread di esecuzione corrente e di una sessione interna con l'identità dell'utente. Associando una sessione all'identità, il contenitore può garantire che la richiesta corrente e tutte le richieste successive dello stesso utente possano essere associate alla stessa sessione, fino alla scadenza della sessione di quell'utente. Questo oggetto di sessione di solito non è lo stesso HttpSessiondell'oggetto, sebbene il primo venga utilizzato per creare e mantenere il secondo. Ogni richiesta successiva dello stesso utente è associata alla sessione utilizzando la riscrittura dell'URL o un cookie di sessione, secondo la specifica Servlet 2.3, capitolo 7.

Come accennato in precedenza nella nostra discussione sull'autorizzazione, ogni azione che il contenitore intraprende e ogni azione che JRE intraprende per conto di quell'utente vengono attentamente controllate per garantire che l'utente abbia il permesso di eseguire l'azione. Per ribadire il nostro esempio precedente, quando il contenitore esegue un servlet per conto dell'utente, verifica che l'utente appartenga all'insieme di ruoli a cui sono state assegnate le autorizzazioni per eseguire quel servlet. JRE 1.4 esegue anche questi controlli per molte azioni, incluso quando si apre un file o un socket. L'autenticazione JRE è un concetto potente e può garantire che ogni richiesta a un contenitore sia essenzialmente sicura.

Attualmente, J2EE fornisce alcuni meccanismi diversi per l'implementazione dell'autenticazione dell'utente. Questi includono l'autenticazione basata su modulo, l'autenticazione client HTTPS e l'autenticazione di base HTTP. JAAS è incluso come metodo di autenticazione richiesto che i contenitori devono supportare. Ma la specifica non è rigorosa su come il contenitore dovrebbe fornire questa funzionalità; pertanto, ogni contenitore fornisce un supporto diverso per JAAS. Inoltre, JAAS di per sé è un framework di autenticazione autonomo e potrebbe essere utilizzato per implementare l'autenticazione del contenitore indipendentemente dal fatto che la specifica lo supporti. Spiegherò questo concetto in modo più dettagliato in seguito.

Ciascuno dei meccanismi di autenticazione fornisce un modo standard per fornire al contenitore informazioni sull'utente. Mi riferisco a questo come realizzazione credenziale . Il contenitore deve ancora utilizzare queste informazioni per verificare che l'utente esista e disponga di autorizzazioni sufficienti per effettuare la richiesta. Mi riferisco a ciò come autenticazione delle credenziali . Alcuni contenitori forniscono la configurazione per impostare l'autenticazione delle credenziali e altri forniscono interfacce che devono essere implementate.

Metodi di autenticazione J2EE

Esaminiamo brevemente alcuni dei metodi più comuni per implementare e configurare l'autenticazione del contenitore.

Autenticazione basata su form

L'autenticazione basata su modulo consente agli utenti di essere identificati e autenticati con il server delle applicazioni J2EE utilizzando qualsiasi modulo HTML. L'azione del modulo deve essere j_security_checke due parametri di richiesta HTTP (campi di input del modulo) devono essere sempre nella richiesta, uno chiamato j_usernamee l'altro j_password,. Utilizzando l'autenticazione basata su modulo, la realizzazione delle credenziali si verifica quando il modulo viene inviato e il nome utente e la password vengono inviati al server.

Di seguito è riportato un esempio di una pagina JSP (JavaServer Pages) che utilizza l'autenticazione basata su form:

 Accedi Inserisci il tuo nome utente:

Inserisci la tua password: