Autenticazione¶
Panoramica¶
SGV GE.CO utilizza meccanismi di autenticazione diversi per modulo, riflettendo l'evoluzione tecnologica del sistema.
Meccanismi per Modulo¶
GeCo.Alfa / GecoService - Spring Security 3.2¶
Configurazione: GeCo.Alfa/WebContent/WEB-INF/spring-security.xml
Componenti:
| Classe | Descrizione |
|---|---|
MAutenticationManager |
Authentication manager personalizzato |
MSecurityImpl |
Implementazione sicurezza |
LoginPresenter |
Presenter per la schermata di login |
LoginDao |
DAO per verifica credenziali |
Flusso di autenticazione:
sequenceDiagram
participant U as Utente
participant V as Vaadin UI
participant SS as Spring Security Filter
participant AM as MAutenticationManager
participant DB as PostgreSQL
U->>V: Accesso a /GeCo.Alfa
V->>SS: DelegatingFilterProxy
SS->>V: Redirect a login
U->>V: Username + Password
V->>AM: authenticate(credentials)
AM->>DB: Verifica credenziali (ApplicationRealm)
DB-->>AM: Risultato
AM-->>V: Authentication token
V-->>U: Accesso garantito
Dettagli:
- Filter chain:
DelegatingFilterProxydi Spring Security - Realm:
ApplicationRealmdi WildFly - Ruoli: Controllo accesso con wildcard (
*role) - Sessione: Gestita da Vaadin + HTTP session
MobileFineAdapterServer - Spring Boot BASIC Auth¶
Configurazione: Classe SecurityConfig
Flusso:
- Richiesta HTTP con header
Authorization: Basic <base64> - Spring Security decodifica credenziali
- Verifica su
ApplicationRealmdi WildFly - Accesso concesso o 401 Unauthorized
REST (Quarkus) - Multi-Tenant X-Realm¶
Configurazione: SGVTenantResolver
Il modulo REST non ha autenticazione utente tradizionale, ma implementa isolamento multi-tenant:
- Ogni richiesta deve includere header
X-Realm: <tenant-name> SGVTenantResolverrisolve il tenant dall'header- Hibernate ORM indirizza al database corretto (isolamento DATABASE-level)
Errore senza header: 500 - No tenant identifier specified
Moduli WildFly (ElaborazioneService, ConnessioneService, OtticoService, VpnMctcService)¶
Autenticazione delegata al container WildFly tramite ApplicationRealm. Configurata in:
standalone.xml(WildFly configuration)web.xml(security-constraint per modulo)
Keycloak SSO (Pianificato)¶
L'integrazione Keycloak e pianificata ma non ancora primaria:
- Stato: In fase di valutazione
- Obiettivo: Single Sign-On centralizzato per tutti i moduli
- File:
keycloak.json(configurazione client)
Gestione Credenziali¶
| Ambiente | Storage | Accesso |
|---|---|---|
| Sviluppo | ~/.m2/settings.xml, Docker .env |
Locale |
| Staging | HashiCorp Vault / K8s Secrets | kubectl get secret |
| Produzione | HashiCorp Vault / K8s Secrets | Solo DevOps |
Regole:
- Mai hardcodare credenziali nel codice
- Mai committare file
.env, certificati, chiavi private - Credenziali di test: in Bitwarden shared vault o chiedere a DevOps
Password Hashing¶
Implementazione (CriptPassword.java)¶
La classe CriptPassword in GeCo.Alfa/src/com/mdatasystem/geco/library/ gestisce l'hashing delle password operatore.
Algoritmo:
public static String criptaPassword(String password, String repartoInseritore)
throws NoSuchAlgorithmException, UnsupportedEncodingException
{
// 1. Concatenazione password + salt (codice reparto)
byte[] input = (password + repartoInseritore).getBytes("UTF-8");
// 2. SHA-512 singolo passaggio
MessageDigest digest = MessageDigest.getInstance("SHA-512");
byte[] hash = digest.digest(input);
// 3. Output: stringa esadecimale uppercase
return Hex.encodeHexString(hash).toUpperCase();
}
| Parametro | Valore | Note |
|---|---|---|
| Algoritmo | SHA-512 | 512 bit output |
| Salt | Codice reparto (repartoInseritore) |
Uguale per tutti gli utenti dello stesso reparto |
| Iterazioni | 1 (singolo passaggio) | Nessun key stretching |
| Output | Stringa hex uppercase (128 caratteri) | |
| Encoding | UTF-8 |
Limiti di Sicurezza Noti
- Nessun key stretching: SHA-512 singolo passaggio e vulnerabile a brute-force/rainbow table
- Salt condiviso: Il codice reparto e lo stesso per tutti gli utenti del reparto
- Standard moderno: bcrypt, scrypt, o Argon2 con salt unico per utente
- La migrazione e pianificata ma richiede reset password per tutti gli utenti
Gestione Sessione¶
Configurazione (web.xml)¶
| Parametro | Valore | File |
|---|---|---|
| Session timeout | 31 minuti | GeCo.Alfa/WebContent/WEB-INF/web.xml |
| Heartbeat interval | 180 secondi | Context parameter in web.xml |
| Push mode | Automatico (async-supported=true) |
Vaadin server push |
| Security domain | ApplicationDomain |
jboss-web.xml |
Thread-Safety (MSecurityImpl.java)¶
La classe MSecurityImpl gestisce la sessione utente con locking esplicito su VaadinSession:
// Scrittura thread-safe su sessione Vaadin
public void setSessionVar(String key, Object valore) {
try {
VaadinSession.getCurrent().getLockInstance().lock();
VaadinSession.getCurrent().setAttribute(key, valore);
} finally {
VaadinSession.getCurrent().getLockInstance().unlock();
}
}
Flusso di logout:
- Rimozione operatore dalla sessione (
ENTITY_USER_SESSION_VAR = null) - Impostazione autenticazione anonima (
AnonymousAuthenticationTokenconROLE_ANONYMOUS) - Reset connessione specifica e reparto inseritore
Keycloak Bridge¶
MSecurityImpl supporta un bridge Keycloak per SSO:
// Flag per bypass validazione Spring Security
private boolean utenteKeycloakValidato = false;
public boolean isUtenteValido() {
// 1. Se Keycloak ha validato, bypass Spring Security
if (this.utenteKeycloakValidato) {
return true;
}
// 2. Fallback: validazione Spring Security tradizionale
Authentication au = SecurityContextHolder.getContext().getAuthentication();
// ...
}
Integrazione LDAP¶
Configurazione (spring-security.xml)¶
GeCo.Alfa supporta autenticazione LDAP opzionale, configurata come bean in spring-security.xml:
| Parametro | Valore |
|---|---|
| Classe | GecoLDapAutentication |
| Server | 110.0.1.153:1389 |
| Base DN | cn=geco,dc=mdatasystem,dc=it |
| User | uid=gecoUser |
| Admin | cn=admin |
Credenziali Hardcoded
Le credenziali LDAP sono attualmente hardcoded nel file spring-security.xml. Devono essere esternalizzate in variabili d'ambiente o vault (vedi Threat Model — A05).