mercoledì 28 gennaio 2015

Autenticazione di accesso alla WebApp

Vai all'indice

In questo post vi illustrerò come ho inserito l'autenticazione degli accessi all'applicazione presentata nell'articolo precedente. La logica proposta è la stessa già vista nell'esempio: Autenticazione sicura con Primefaces.

Gli utenti abilitati all'ingresso sono gli stessi gestiti nell'applicazione, quindi utilizzerò la tabella Utente per salvare le credenziali di accesso per la login. Nello specifico ricaverò lo username concatenando i campi Cognome e Nome, mentre per la gestione della password inserirò un nuovo campo nella tabella Utente.

Riporto di seguito l'istruzione SQL per la modifica della tabella utente.

ALTER TABLE utente add COLUMN password VARCHAR(255);


Inoltre l'istruzione seguente inizializza il campo password col valore cifrato 'testtest00'.

update utente set password='1000:c5cca4907214bb9fb4d9e978bb970f63875350f3456ea492:49685e1f51d4cdebb3e3c8127ae05264fac87b50d473ea2b';

Per la protezione del campo password utilizzerò un meccanismo di cifratura che che mi permetterà di "cammuffare" l'informazione. Questi metodi sono detti funzioni hash o cifratura a senso unico e sono utilizzati per la cifratura delle password. E' buona norma non memorizzare le password in chiaro sul sistema, ma soltanto la loro cifratura. Quando un utente vuole accedere al sistema, il meccanismo di autenticazione richiede la password, la cifra con l'algoritmo di hashing considerato e confronta la password cifrata con quella memorizzata sul sistema per l'utente in questione. Se le due password cifrate coincidono, all'utente è permesso accedere al sistema.

Dall'esempio Autenticazione sicura con Primefaces importo i file necessari per l'implementazione del controllo accessi.

  • Il file login.xhtml contiene il form per l'autenticazione e viene impostato come welcome-page dell'applicazione, 
  • al bean associato loginBean aggiungo l'interrogazione delle chiavi di accesso nel database e la crittografia per rendere sicure le password degli utenti, 
  • la classe util inserita nel pacchetto it.prototype.utils contiene i metodi HttpSession e HttpServletRequest, 
  • la classe AuthFilter contiene il filtro di autenticazione e va inserito nel pacchetto it.Filters. 

Modifico il file web.xml indicando login.xhtml come nuova welcome-page, mentre nel file faces-config.xml inserisco il tag navigation-rule che definisce le regole di navigazione.
Aggiungo la nuova classe hashpass che contiene l'algoritmo di hashing per la crittografia della password.



Nel prossimo post vedremo come implementare la gestione degli uffici a cui appartengono gli utenti e delle applicazioni a cui essi sono abilitati.

La WebApp aggiornata con il controllo accessi è scaricabile da GitHub.

Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!

giovedì 22 gennaio 2015

WebApp con Spring Hibernate e Primefaces

Vai all'indice

L'obiettivo di questo post è la realizzazione di un'architettura enterprise e multidatasource costruita integrando i framework Spring, Hibernate e Primefaces. La web application proposta in questo esempio gestisce i dati contenuti nel database Apache Derby già utilizzato in precedenza di cui riporto di seguito la struttura.



Per fare questo riprenderò i concetti visti nei post Introduzione a Spring con esempio pratico e Inserire, cancellare modificare righe su Datatable Primefaces. Nel primo esempio vi ho mostrato come mappare il modello dati e costruire le classi per la gestione delle informazioni provenienti dal database grazie all'utilizzo di Spring e Hibernate, mentre nel secondo abbiamo visto la gestione grafica dell'interfaccia utente con Primefaces.

La costruzione della WebApp


Per prima cosa creo una nuova WebApp mantenendo l'interfaccia già vista nell' esempio precedente, pertanto, dopo avere definito un nuovo progetto Maven, importo la pagina index.xhtml, i bean associati, i file web.xml e faces-context.xml di configurazione.

Dall'esempio Introduzione a Spring con esempio pratico importo i pacchetti contenenti le entità e le classi DAO. Inoltre inserisco il file applicationContext.xml di Spring nel percorso WebContent > WEB-INF.

A questo punto, dopo l'importazione dei moduli di nostro interesse dai due progetti, è necessario integrare la parte di gestione dati con l'interfaccia grafica, riporto di seguito le modifiche salienti ai singoli moduli.
Come prima cosa aggiungo nel web.xml i listener di Spring.

  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
      /WEB-INF/applicationContext.xml
      </param-value>
  </context-param>
  <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
   </listener>
   <listener>
  <listener-class>
   org.springframework.web.context.request.RequestContextListener
  </listener-class>
   </listener>

La classe ContextLoaderListener è un ServletContextListener, che viene chiamato all’avvio del Tomcat, per inizializzare e caricare il context di Spring nell'applicazione, mentre RequestContextListener serve a Spring per dichiarare lo scope associato al bean.
Grazie al parametro contextConfigLocation è possibile indicare il percorso del file di configurazione del contesto di Spring.

   <application>
     <el-resolver>
      org.springframework.web.jsf.el.SpringBeanFacesELResolver
     </el-resolver>
   </application>

Sia JSF che Spring gestiscono un proprio IoC Container, per cui è necessario trovare un modo per farli comunicare, ed è Spring che se ne occupa. Inserendo nel faces-context.xml di JSF la definizione della classe el-resolver che delega a Spring tutte le espressioni EL che JSF non riesce a risolvere, tra cui gli stessi bean definiti nel container di Spring.

  <dependency>
     <groupId>log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>1.2.16</version>
  </dependency>
  <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.5.6</version>
  </dependency>
  <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-log4j12</artifactId>
     <version>1.5.6</version>
  </dependency>


Nel pom.xml inserisco tutte le dipendenze di Spring, Hibernate e Primefaces già viste nei due esempi sopra citati. Inoltre ho aggiunto la dipendenza c3p0 per la gestione del pool di connessione e le dipendenze slf4j e log4j per inserire nel progetto la gestione di un sistema di logging.

@ManagedBean(name = "utenti")
@RequestScoped
public class utentiBean implements Serializable {

    private static final long serialVersionUID = 1L;
    public int userid;
    public String nome;
    public String cognome;
    public String ruolo;
    private Date data;
    public String via;
    public String citta;
    public String telefono;
    public List<Utente> users;
utenteBean utente;
    
    @ManagedProperty(value="#{utenteDao}")
    UtenteDao utenteDao;
    
    // Definizione Getter e Setter

    private static final ArrayList<utenteBean> utentiList = new ArrayList<utenteBean>();

    public ArrayList<utenteBean> getUtentiList() {
        return utentiList;
    }
    
    @PostConstruct
    public void init() {
   users = utenteDao.getAll();
   inizializza();
   initdata();
}

    public String addAction() {
   
     // Istanzio e salvo gli oggetti utente e dettaglioutente
     Dettaglioutente dettUte = new Dettaglioutente(this.data, this.via, this.citta, this.telefono);
     Utente ute = new Utente(this.nome, this.cognome, this.ruolo);
     utenteDao.saveDetUte(ute, dettUte);
   
     inizializza();

     nome = "";
     cognome = "";
     ruolo = "";
     via = "";
     citta = "";
     telefono = "";
     initdata();
     return null;
    }
    
    public void onEdit(RowEditEvent event) { 
        Dettaglioutente dettUte = new Dettaglioutente(((utenteBean) event.getObject()).getUserid(), ((utenteBean) event.getObject()).getData(), ((utenteBean) event.getObject()).getVia(), ((utenteBean) event.getObject()).getCitta(), ((utenteBean) event.getObject()).getTelefono());
        Utente ute = new Utente(((utenteBean) event.getObject()).getUserid(), ((utenteBean) event.getObject()).getNome(), ((utenteBean) event.getObject()).getCognome(), ((utenteBean) event.getObject()).getRuolo());  
        // Aggiorno l'utente
        utenteDao.aggUte(ute, dettUte);
        inizializza();
        FacesMessage msg = new FacesMessage("Record modificato",((utenteBean) event.getObject()).getNome());  
        FacesContext.getCurrentInstance().addMessage(null, msg);  
    }  
       
    public void onCancel(RowEditEvent event) {  
        FacesMessage msg = new FacesMessage("Modifiche annullate");   
        FacesContext.getCurrentInstance().addMessage(null, msg); 
    } 
    
public void delete(utenteBean std){ 
// Elimina l'utente
        utenteDao.deleteUtente(std.getUserid());
        inizializza();
FacesMessage msg = new FacesMessage("Record cancellato");   
        FacesContext.getCurrentInstance().addMessage(null, msg);
}

public void inizializza(){
        utentiList.clear();
   List<Utente> users = utenteDao.getAll();
for (Utente user : users) {
Dettaglioutente dettuser = utenteDao.getDettaglioutente(user.getuserId());
utenteBean utentetmp = new utenteBean(user.getuserId(), user.getNome(), user.getCognome(), user.getRuolo(), dettuser.getDataNascita(), dettuser.getVia(), dettuser.getCitta(), dettuser.getTelefono());
       utentiList.add(utentetmp);
}
}

public void initdata(){
    String dateStr = "1970-01-01T00:00:00.000+01:00";
    SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
    try  {
    data = sdf.parse(dateStr.replaceAll(":(?=..$)", "")); 
    } catch (ParseException e) { 
        System.out.println("Anomalia parser data " + sdf); 
    }
}



UtentiBean è la classe di gestione della pagina index.xhtml ed è il modulo chiave su cui agire per collegare la parte di presentazione con la gestione dei dati.
L'annotazione @managedbean è usata per configurare l’iniezione di dipendenza in Spring ed è associata alla classe UtenteDao che contiene i metodi di interfaccia per l'accesso alle tabelle utente.
@PostContruct è l'annotazione applicata al metodo init() per indicare che deve essere chiamato dopo che tutte le dependency injection sono state completate. Nel nostro caso specifico è utilizzata per caricare i campi del Datatable coi dati estratti dal database.
Le chiamate ai metodi della gestione dei dati vengono attivate tramite gli eventi di inserimento, cancellazione e modifica dei dati presenti nel Datatable di Primefaces.
A questo punto la stesura del codice è terminata ed è possibile testare l'applicazione.



L'interfaccia grafica gestisce i dati relativi agli utenti ed è formata da un'unica pagina web divisa in due schede. La scheda inferiore contiene il modulo di inserimento nuovo utente, mentre la scheda superiore contiene un oggetto Datatable che permette la visualizzazione, l'aggiornamento e la cancellazione dei dati inseriti. Poichè a livello di Database i dati relativi agli utenti sono divisi in 2 tabelle (utente e dettaglioutente tra cui esiste una relazione uno a uno) ma l'oggetto datatable è unico, per comodità ho mappato i dati nel POJO UtenteBean prima di caricarli nel Datatable.

Nei prossimi post vedremo come implementare e completare il progetto appena iniziato.

Anche questo esempio è scaricabile da GitHub.

Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!