MokaByte 78 - 8bre 2003 
La sicurezza nella servlet API
di
Giovanni Puliti
Come implementare meccanismi di autenticazione ed autorizzazione nelle web application tramite la Servlet API

Introduzione
Spesso accade di dover realizzare applicazioni web basate su servlet, su pagine JSP (più comunemente su entrambe) in cui l'accesso dell'utente a determinate risorse debba essere subordinato ad una serie di vincoli in modo da garantire un opportuno livello di sicurezza.
Più precisamente può essere necessario poter concedere l'accesso solo a determinate persone (autentication) ed in base al profilo utente fornire l'accesso solo a specifiche risorse (autorization). Inoltre spesso è necessario garantire che solo le parti coinvolte nella comunicazione, l'utente ed il server, possano accedere in modo riservato alle informazioni in scambiate fra i due (confidentiality). Strettamente legato a quest'ultimo aspetto vi è quello della integrità delle informazioni: nessuno deve poter alterarne il contenuto durante il tragitto fra utente e server i quali devono poter verificarne l'integrità (integrity).

Le considerazioni che verranno qui esposte non sono prerogativa esclusiva del mondo delle servlet, ma sono in genere valide per tutti quei casi in cui una risorsa statica (un file HTML o di testo) o dinamica (servlet, pagine JSP) sia accessibile dall'esterno e se ne debbano configurare gli aspetti legati alla sicurezza appena accennati.
Per questo quanto qui affrontato verrà visto in ottica web-application, spazio in cui di fatto una servlet vive. Alcune tecniche di programmazione in realtà non hanno a che fare con il processo di configurazione delle servlet o di Java ma più spesso sono procedure di personalizzazione del server web e della web application.
Nell'articolo verranno presentate le tecniche standard per proteggere le risorse e per certificare l'identità di server e del client cercando di semplificare al massimo il discorso limitatando la trattazione al caso si semplici web application e semplici servlet. L'argomento della gestione della sicurezza è molto vasto ed in alcuni punti esula dall'argomento sui cui è centrato il capitolo. Per chi fosse interessato a maggiori approfondimenti si rimanda alla bibliografia ufficiale.

 

Autenticazione e protezione di risorse
Per semplificare il discorso si ipotizzerà di dover proteggere una servlet dall'accesso pubblico e che tale servlet viva all'interno di una web application denominata secret.
L'obiettivo finale è quello di fornire accesso alla servlet solo se l'utente fornisce le corrette credenziali: si deve quindi utilizzare un meccanismo che permetta l'autenticazione e la autorizzazione all'accesso a determinate risorse.
Prendendo spunto dal meccanismo degli utenti e gruppi tipico di Unix, Java utilizza un sistema di autenticazione ed autorizzazione basato sui ruoli: solo dopo aver accertato che un utente appartiene ad un determinato ruolo, si potrà fornire l'accesso solo alle risorse (statiche o dinamiche) autorizzate per quel determinato ruolo.

Il processo di autenticazione può essere implementato in vari modi: nel caso più semplice questo comporta l'inserimento di userid e password, mentre volendo adottare un modello con uno standard di sicurezza più alto si potrà implementare un meccanismo di riconoscimento reciproco basato su chiavi e certificati digitali.

Una volta accertata l'identità dell'utente, il servlet container agisce utilizzando il concetto di security constraint, associando il ruolo ad un insieme di risorse.
Il servlet container in genere utilizza vari meccanismi per definire il set di utenti ed associare i ruoli: la forma più semplice, utilizzata ad esempio anche da Tomcat, è quella che prevede l'uso di un file in formato XML in cui sono memorizzate userid, password e ruolo. Ad esempio in Tomcat al momento della installazione sono definiti alcuni utenti all'interno del file tomcat-users.xml, presente nella directory conf della installazione; tale file in genere è così strutturato:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<user username="tomcat" password="tomcat" roles="tomcat,manager"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>

In questo caso manager è per definizione il ruolo corrispondente all'amministratore del server, usato per accedere alla console di amministrazione del server stesso. Il file permette di definire una terna composta da (username, password, ruolo) tramite il tag <username>.
Si noti che essendo il file utilizzato come configurazione del server, non è possibile in questo caso definire meccanismi di accesso ai dati personalizzati per ogni singola applicazione. Nel caso in cui fosse necessario ricorrere a meccanismi più sofisticati e customizzati si dovrà necessariamente utilizzare tecniche più complesse descritte in seguito.
Una volta definito un utente o un gruppo di utenti, all'interno della applicazione si dovranno definire le seguenti impostazioni: la modalità di login, le risorse della applicazione da proteggere associandole a determinati ruoli, il sistema di trasporto dei dati. Tali informazioni sono inserite tramiti appositi tag all'interno del file web.xml.
I modelli di autenticazioni di una risorsa web sono i seguenti:

  • BASIC e FORM: in questo caso l'autenticazione avviene tramite l'utilizzo di ruoli (roles) associati a determinati utenti ed il meccanismo di riconoscimento avviene utilizzando le funzionalità offerte direttamente dal container.
  • CUSTOM: in questo caso il processo di riconoscimento viene implementato in modo manuale dal programmatore che può far uso delle API offerte da Java in tema di sicurezza o ricorrere a tecniche personalizzate.
  • DIGEST: basato su certificati digitali


Autenticazione BASIC e FORM
Questi due casi sono molto simili fra loro e si basano essenzialmente sulle funzionalità offerte dal server HTTP: l'utente fornisce una coppia di valori, userid e password, al momento in cui l'utente richiede di accedere ad una risorsa protetta. Questo meccanismo permette di proteggere genericamente una risorsa associata ad un determinato URL, sia essa una servlet o una pagina JSP ma anche un file HTML, una immagine GIF o un file generico.
Ad ogni tentativo di accesso ad un URL protetto, tramite un semplice meccanismo di scambio di credenziali fra browser e server, si determina se l'utente ha già effettuato un processo di autenticazione (login) ed in tal caso se il ruolo associato corrisponde a quello necessario per poter accedere alla risorsa. La definizione di una risorsa protetta e l'associazione al ruolo avviene all'interno del file web.xml che potrebbe essere così definito:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>secretservlet</servlet-name>
<servlet-class>
com.mokabyte.mokabook.servlets.security.basic.SecretServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>secretservlet</servlet-name>
<url-pattern>/secretservlet</url-pattern>
</servlet-mapping>
. . .
<security-constraint>
<display-name>basic</display-name>
<web-resource-collection>
<web-resource-name>Secured Web Collection</web-resource-name>
<url-pattern>/</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
<security-role>
<description>una autorizzazione per il manager</description>
<role-name>manager</role-name>
</security-role>
. . .
</web-app>


In questo caso nel deployment descriptor dell'applicazione viene definita la servlet com.mokabyte.mokabook.servlets.security.basic.SecretServlet alla quale è associato il nome secret. L'URL mapping con il quale è possibile invocare la servlet è /secretservlet.
Il tag <security-constraint> inizia la definizione di tutti gli aspetti legati alla sicurezza. Il tag <web-resource-collection> definisce il set di risorse che si vogliono proteggere: in questo caso tramtie il tag <url-pattern>

<url-pattern>/</url-pattern>

si proteggono tutti gli URL associati alla applicazioni; possono essere presenti un numero arbitrario di coppie <url-pattern>. Tramite i tag

<http-method>GET</http-method>
<http-method>POST</http-method>

entrambi i metodi di invocazione GET e POST saranno soggetti alle restrizioni imposte.
Il pezzo di script XML

<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>

definisce invece un ruolo da associare al constraint: in questo caso manager potrà accedere alle risorse protette e definite in <web-resource-collection>.
Infine il tag login-config permette di specificare il tipo di autenticazione richiesta: in questo caso la forma BASIC, gestita completamente dal servlet container.

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>

il <real-name> serve per specificare quale dominio applicativo debba essere associato al security constraint, cosa utile nel caso in cui l'applicazione serva per più domini.
Infine segue l'elenco dei ruoli ammessi per questa applicazione.

<security-role>
<description>una autorizzazione per il manager</description>
<role-name>manager</role-name>
</security-role>

Nel caso di autenticazione BASIC all'utente verrà presentata la classica finestra del browser in cui si chiede di immettere i dati di autenticazione (userid e password).


Figura 1
- al momento della autenticazione BASIC il browser mostra
una finestra di dialogo in cui immettere userid e password

 

Questo meccanismo di autenticazione non è quasi più utilizzato dato che è poco user friendly e certamente non più alla moda. Ormai tutte le applicazioni web mostrano una pagina HTML personalizzata in cui inserire i dati di accesso. Questo permette di mostrare all'utente una pagina coerente con il resto della applicazione, di mostrare anche maggiori dettagli informativi di aiuto ed anche una pagina di errore personalizzata nel caso in cui l'utente immetta dati non validi.
In figura 2 è riportato il form HTML di autenticazione richiesto per poter entrare all'interno del forum di MokaByte: in questo caso l'utente riceve una pagina gradevole ed esplicativa delle informazioni da eseguire: ad esempio nel caso in cui l'utente non ricordi la password potrà ciccare su un link ed andare nella pagina della Community di MokaByte da cui farsi inviare per email i suoi dati personali.

 


Figura 2
- Con l'autenticazione di tipo FORM è possibile visualizzare
all'utente una pagina HTML contenente il form di registrazione.
In questo caso l'utente può ricevere un numero maggiore di
informazioni e si troverà più a suo agio dato che la pagina di
login ha lo stesso look and feel del resto della applicazione web

Per poter attivare il sistema di autenticazione basato su form HTML è necessario modificare il file web.xml introducendo al posto di BASIC il valore FORM

<login-config>
<auth-method>FORM</auth-method>
<realm-name>default</realm-name>
<form-login-config>
<form-login-page>/login.htm</form-login-page>
<form-error-page>/error.htm</form-error-page>
</form-login-config>
</login-config>

Si noti come in questo caso si deve specificare il nome del file HTML da utilizzare come form di login ed anche la pagina di errore.
Anche nel caso di utilizzo di un form HTML il processo di autenticazione è a completo carico del servlet container: il form infatti invoca un URL particolare (j_security_check) provvedendo a passare parametri particolari (j_username e j_password); sinteticamente il codice HTML necessario per definire il form è il seguente:

<form action='j_security_check' name="loginForm" method="POST">
<input type="text" name="j_username" size="16" maxlength="16" id="username"/>
<input type="password" name="j_password" size="16" maxlength="16" id="password"/>
<input type="submit" value="Entra" name="submit">
</form>

Ovviamente il resto della pagina può essere abbellita a piacimento inserendo vari elementi grafici necessari per abbellire la pagina e personalizzarla a piacimento.
Il sistema appena visto è sicuramente poco affidabile in quanto a livello di sicurezza e non consente molte personalizzazioni: il fatto stesso che i dati siano memorizzati in un file di testo (tomcat-users.xml) non offre certamente grandi garanzie di sicurezza, se qualcuno riesce ad accedere a tale file di testo.
Un piccolo miglioramento si può ottenere utilizzando database relazionali, alberi LDAP o altro ancora verso i quali la applicazione web potrà effettuare la ricerca di userid e password in vario modo. In [TOM] ad esempio viene mostrato come utilizzare un database relazionale in cui memorizzare tali informazioni e come customizzare l'applicazione per accedere a tali dati.


Figura 3 - Con poco lavoro è possibile abbellire la pagina di login in modo da rendere l'utente a proprio agio e non fare apparire il login come di qualcosa di slegato dal resto

 

Recupero delle informazioni client
Ad ogni invocazione il servlet può accedere ad una serie di invocazioni riguardanti la sicurezza che sono inviate dal client all'interno dell'header HTTP.
Queste informazioni possono essere ricavate tramite alcuni metodi messi a disposizione dalla API: i metodi getRemoteUser() e getAuthType() restituiscono il nome dell'utente ed il tipo di autenticazione utilizzata.
A partire dalla servlet API 2.2 è stato inserito il metodo getUserPrincipal(), che restituisce un oggetto implementazione dell'interfaccia javax.security.Principal:

public javax.security.Principal HTTPServletRequest.getUserPrincipal()

Il concetto di principal è stato introdotto per uniformare i meccanismi di sicurezza in J2EE (è utilizzato ad esempio anche in EJB per definire le policy di accesso ai metodi di session ed entoty beans): può essere un utente, un gruppo, una azienda o semplicemente un identificativo di un soggetto che accede alla risorsa.
Principal include il metodo getName() che restituisce il nome del principal. Da notare che getUserPrincipal() deve essere preferito per mantenere omogeneità in J2EE, anche se la servlet API include il metodo getRemoteUser() per compatibilità con lo standard universalmente adottato in CGI. Infine il metodo

public boolean isUserInRole(String Role)

permette di verificare se l'utente loggato appartiene o meno ad un determinato ruolo, consentendo di realizzare politiche di accesso variabili in funzione del ruolo utente.

 

Autenticazione di tipo custom
Molto spesso accade che per l'autenticazione non sia sufficiente affidarsi al meccanismo offerto dall'application server (meccanismi BASIC o FORM): se userid e password non sono le uniche informazioni da immettere o se si vuole operare in modo più personalizzato nella procedura di login, si deve per forza ricorrere a sistemi scritti appositamente per rispondere alle proprie esigenze. Molte possono essere le tecniche da adottare in questo caso: in [SER] ad esempio viene mostrato un servlet che controlla se l'utente ha effettuato il login verificando se nella sessione è stato inserito un determinato valore, una stringa o un oggetto (vedi oltre).
In questo caso tutte le richieste fatte dagli utenti sono intercettate da questa servlet: se l'utente è loggiato la servlet inoltrerà la richiesta alla risorsa invocata dal client, altrimenti rimanderà alla pagina contenente il form di login. Tale form poi invocherà un'altra servlet che provvederà a controllare se i dati sono corretti e procedere in tal caso a creare in sessione di dati dell'utente.
Una versione più raffinata di tale sistema potrebbe prevedere l'utilizzo della classe Principal da utilizzare come wrapper delle informazioni relative all'utente loggato. Questo sistema ha il vantaggio di essere più standard e di inserirsi in modo più armonico nella programmazione J2EE: altri oggetti potrebbero infatti aver bisogno di accedere a tali oggetti.
Una variante più elegante di quella basata sulla servlet-intercettatutto potrebbe prevedere l'utilizzo di un filtro: questi oggetti inseriti nella specifica con la API 2.3 (vedi oltre) non sono altro che particolari servlet le quali hanno il solo compito di intercettare tutte le richieste per gli URL sulle quali sono mappate e di inoltrare poi la richiesta altrove.
Questa soluzione, oltre a sfruttare in modo migliore le potenzialità offerte dalla API, ha il grosso vantaggio di non impattare sui mapping definiti per le servlet o per le altre risorse della applicazione. Ad esempio nelle moderne web application basate sul modello Model-View-Controller (Struts [STRU] o Mokapackages [MBPAK]), spesso tutte le invocazioni corrispondenti alla esecuzione di una qualche business logic sono mappate con URL del tipo *.run o *.do, mentre le invocazioni di pagine HTML dinamiche (in MVC dette viste) sono spesso mappate con URL del tipo *.show o *.view.
A questi URL sono poi associati determinate servlet che inoltrano le richieste verso opportune risorse: nel caso di *.run ad esempio verso classi action che eseguono la business logic, mentre per le *.show verso pagine JSP.
Il motivo per cui si adottino queste tecniche, che ad una prima analisi possono sembrare prive di senso, è alla base della potenza del pattern MVC: dato che una sua trattazione esula dagli scopi di questo capitolo si rimanda a [MVC].
Appare evidente che mappare una altra servlet per entrambi gli URL-pattern in modo da effettuare i controlli sui login risulta essere piuttosto scomodo ed anche rischioso: si può avere la certezza che il servlet container invochi sempre prima la LoginServlet prima di ogni altra? E poi sovrapponendo due URL mapping simili (/ vince su *.run?) si può avere la certezza che entrambi verranno presi in considerazioni ed eseguite le rispettive servlet? Per esperienza queste situazioni portano ad impredicibilità del comportamento della applicazione, sia all'interno dello stesso application server che fra prodotti differenti.
I filtri invece essendo delle particolari servlet che per specifica eseguite prima di ogni altro (o dopo) non introducono variabili indeterminabili e non impattano con il set di mapping specificato per le servlet, avendone uno tutto loro.
Di seguito è riportato un esempio che mostra come potrebbe essere implementato questo meccanismo customizzato.

<Nota>Fra gli esempi allegati non è stato incluso un esempio che mostra come realizzare un login personalizzato. Il lettore potrà facilmente realizzare una applicazione completa partendo dalle porzioni di codice qui riportato. Una implementazione completa di che supporti l'autenticazione custom, unitamente alla gestione dei ruoli utente, è presente all'interno di MokaPackages, il framework di MokaByte in MVC: questo prodotto verrà presto messo in vendita sotto forma di libro e codice associato. [MVC]. </nota>

Il servlet che effettua il controllo potrebbe essere così implementato:


public void service(HttpServletRequest req,
                    HttpServletResponse res)
                    throws IOException, ServletException {
  . . .
  // Ricava un oggetto LoggedUser dalla sessione
  LoggedUser loggedUser = (LoggedUser)

  
req.getSession().getAttribute("loggedUser");
  if (loggedUser != null) {
    String role = loggedUser.getUserRole();
    // page = ricava la pagina dalla request
    // invocata dal client oppure in altro modo
    res.sendRedirect(res.encodeRedirectURL(page));
  }
  else{
    // lancia una eccezione proprietaria
    throw new UserNotLoggedException("Operazione non consentita,
                                      utente non loggato");
  }
}

In questo caso il servlet mappato per rispondere a tutte le richieste dei client controlla se in sessione è presente un oggetto di tipo LoggedUser, che deve essere inserito in sessione al momento del login. Ad esempio se fosse un servlet ad effettuare il login si potrebbe scrivere

public void service(HttpServletRequest req,
                    HttpServletResponse res)
                    throws IOException, ServletException {
  // ricava i dati utente dalla sessione
  String UserId = httpServletRequest.getParameter("userId");
  String UserPassword = httpServletRequest.getParameter("passwd");

  // con una qualche logica di collegamento verso
  // un database remoto effettua il login passando
  // userid e password. Viene restituito un oggetto
  // Role associato all'utente
  // utile se si vuole implementare una logica di
  //
controllo basata sui ruoli
  Role role = login(UserId, UserPassword);

  if (role != null){
    HttpSession session = httpServletRequest.getSession();
    LoggedUser user = new LoggedUser(UserId, UserPassword,role);
    session.setAttribute("loggedUser",user);
    // inoltra la risposta verso un altro servlet o pagina JSP
    // page = ricava la pagina dalla request invocata dal
    // client oppure in altro modo
    res.sendRedirect(res.encodeRedirectURL(page));
  }
}

LoggedUser è una classe particolare utilizzata in MokaPackages ([MBPACK]) il framework di MokaByte il quale implementa una struttura simile a Struts: in questo caso LoggedUser permette anche di memorizzare il ruolo dell'utente loggiato e quindi consente all'interno del metodo service del servlet di controllo di verificare se ad esempio una azione associata all'URL add-item-to-cart.run è eseguibile dall'utente in questione. In questo caso ogni azione deve essere definita associando un ruolo.
In MBPACK il servlet che effettua il login in realtà è una Action Java mentre quello che effettua il controllo è un FilteServlet che filtra in modo trasparente tutte le invocazioni da parte del client.

 

Autenticazione basata su certificati
Nel caso in cui si desideri utilizzare un livello di sicurezza alto, si può ricorrere alla autenticazione di tipo DIGEST, basata sul meccanismo dello scambio di chiavi pubbliche e private (certificati).
Questo argomento è molto vasto e richiede una buona conoscenza di base delle tecniche e della teoria legata ai certificati, ai meccanismi di autenticazione e soprattutto a come il server utilizzato gestisce tali oggetti.
Non si entrerà nel dettaglio di questi aspetti principalmente per due motivi: per prima cosa questi aspetti non sono strettamente legati al mondo della programmazione delle servlet e dato che lo spazio qui a disposizione è limitato non se ne darà una spiegazione dettagliata ed approfondita. Inoltre molti dettagli legati al funzionamento dei certificati digitali ed al meccanismo di autenticazione DIGEST sono legati non tanto al servlet container, ma piuttosto al server HTTP utilizzato a fronte del container. Ad esempio in una tipica configurazione di produzione Apache HTTP Server viene utilizzato in abbinamento con Jakarta-Tomcat: il primo svolge tutte le operazioni di interfacciamento verso il client web fra cui anche effettuare l'autenticazione tramite certificati digitali. E' infatti preferibile utilizzare gli strumenti di configurazione e le funzionalità del server Apache per questo lavoro piuttosto che basare tutto il lavoro su Tomcat, sia per motivi di prestazioni che per il maggior supporto offerto dal server HTTP.
Normalmente in tale scenario Tomcat riceve, se il connettore lo permette, le informazioni di autenticazione inoltrate dal server HTTP posto come front-end verso il client.
Nel caso in cui si decida di configurare direttamente il servlet container per l'autenticazione DIGEST si dovrà modificare il file web.xml cambiando la parte relativa al tag <login-config>

<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>

Inoltre si può forzare ad utilizzare il protocollo SSL per il trasporto dei dati modificando un pezzo del blocco <security-constraint> di web.xml

<user-data-constraint>
<transport-guarantee>
INTEGRAL
</transport-guarantee>
</user-data -constraint>

In questo caso il valore INTEGRAL garantisce che i dati ricevuti siano integri ovvero che non siano stati modificati durante il tragitto. L'altro valore consentito, CONFIDENTIAL, garantisce che i dati non siano stati letti da una terza parte non autorizzata e di fatto implica anche che i dati siano integri.
In genere in questi casi è il server che decide come e quando effettuare tutti controlli necessari per garantire tali livelli di protezione.

Una applicazione web basata su servlet o pagine JSP può a questo punto effettuare i controlli necessari accedendo a tali informazioni tramite i metodi messi a disposizione dalla API.
Ad esempio può stabilire se la connessione è sicura tramite il metodo

public boolean ServletRequest.isSecure()

che restituisce il valore true se il server reputa che la connessione con il client rispetta i requisiti minimi di sicurezza (se e come la connessione sia sicura dipende da molti fattori, fra cui stranamente fino a poco tempo fa anche la localizzazione geografica dato che algoritmi di protezione a 128 non potevano essere esportati dagli USA).
Con gli attributi di sicurezza javax.servlet.request.chyper_suite e javax.servlet.request.key_size si possono avere informazioni sull'algoritmo utilizzato e sulla dimensione delle chiavi usate per crittografare i dati.
Quando un client viene autenticato in modalità CLIENT-CERT la servlet può utilizzare il metodo getUserPrincipal() per ricavare il nome dell'utente ricavandolo dal campo Distinguished Name del certificato.
La servlet può ricavare il certificato dalla request ed operare tutti i controlli applicativi del caso:

java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)
request.getAttribute("java.security.cert.X509Certificate");

Se il server supporta J2SE1.2 (JDK 1.2) allora in questo caso si otterrà un oggetto java.security.cert.X509Certificate che rappresenta un certificato X509v.

 

Conclusione
Con questo articolo si è voluto colmare una piccola carenza nella documentazione pubblicata su MokaByte relativamente alle servlet API: infatti sia sul libro di MokaByte che nei vari articoli non si era mai parlato approfonditamente di questi argomenti. A parte il caso della autenticazione CUSTOM, il motivo di questa assenza è, come il lettore si sarà reso conto, che in effetti non si tratta di temi non strettamente legati alla programmazione Java e Servlet, ma piuttosto qualcosa che ha a che fare con il settore della gestione sistemistica dei server HTTP, o della sicurezza in genere.
Partendo dagli esempi mostrati in questo articolo si potranno facilmente riprodurre scenari più o meno semplici in cui realizzare sistemi di protezione basati sui vari sistemi di autenticazione e protezione. Purtroppo in determinati casi (vedi autenticazione DIGEST) non è possibile approfondire oltre l'argomento per mancanza di spazio.

 

Bibliografia
[JSR 154] - Sito web ufficiale del Servlet API 2.4 working group, JSR 154
http://www.jcp.org/en/jsr/detail?id=154

[API] - Sito web ufficiale della servlet API http://java.sun.com/products/servlet

[DOWN] - Download page for the J2EE 1.4 specification
http://java.sun.com/j2ee/download.html#platformspec

[STM] - "Servlet Best Practices, Part 1" e seguenti, di aa.vv.
http://www.onjava.com/pub/a/onjava/excerpt/jebp_3/index1.html

[SER] - "Java Servlet Programming" di Jason Hunter, William Crawford, Ed. HOPS

[MBPAK] - Home page del progetto Mokapackages: www.mokabyte.it/mokapackages

[MVC] - "MokaShop, il negozio online di MokaByte: Realizzare applicazioni J2EE multicanale - I parte" di Giovanni Puliti, http://www.mokabyte.it/2002/02/devj2ee_1.htm e seguenti

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it