devo usare una treemap, chiedo scusa...
devo usare una treemap, chiedo scusa...
Più pratica in futuro...
Mi piace molto la TreeMap perché ha dei metodi comodi che mi facilitano il lavoro come conainsValue(). Tu mi consigli di riscrivere tutto con gli array? Ho scritto il modulo di autenticazione nella servlet lascindo per ora sospeso il discorso delle sessioni. Mi funziona tutto tranne questo metodo:
Uso CercaUtente per verificare se in TreeMap esiste un dato utente. In pratica i valori della TreeMap sono degli array di stringhe che contengono nome utente più password convertita in hash. Se scrivo:codice:public boolean CercaUtente(TreeMap<Integer,String[]> Matrice, String [] VettoreRiga) { return Matrice.containsValue(VettoreRiga); }
Ottengo false ma ti assicuro che Utente esiste in Matrice. Se scrivo:codice:boolean vero = false; vero = rf.CercaUtente(Matrice, Utente); System.out.println(vero);
ottengo questo:codice:System.out.println(Matrice.get(0)[0]); System.out.println(Matrice.get(0)[1]); System.out.println(Utente[0]); System.out.println(Utente[1]); System.out.println(Matrice.get(0).length); System.out.println(Utente.length); System.out.println(Matrice.get(0).equals(Utente));
codice:Topolino 04b17b4383 Topolino 04b17b4383 2 2 false
Ultima modifica di giannino1995; 11-08-2018 a 18:06
Più pratica in futuro...
Ho risolto, non si può usare containsValue() come pensavo.
Per ora la servlet è strutturata in questo modo?
cosa ne pensi? Posso procedere o è una maialata totale?codice:package web1; import java.io.IOException; import java.io.PrintWriter; import java.util.TreeMap; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns = "/LoginFiltrata") public class LoginFiltrata extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String UserID = request.getParameter("UserID"); String Password = request.getParameter("Password"); FromStringToHash HashText = new FromStringToHash(Password,"pall0"); String[] Utente = {UserID, HashText.getHashText()};ServletContext context = getServletContext();String fullPath = context.getRealPath("/WEB-INF/users.txt");TreeMap<Integer,String[]> Matrice = new TreeMap<Integer,String[]>(); FromTxtToMatrix rf = new FromTxtToMatrix(); Matrice = rf.LeggiFile(fullPath);if (rf.CercaUtente(Matrice, Utente)) {response.setContentType("text/html"); PrintWriter writer = response.getWriter();writer.println("<html><body>"); writer.println("Benvenuto " + UserID + "!"); writer.println("</body></html>"); writer.close(); } else {response.setContentType("text/html"); PrintWriter writer = response.getWriter();writer.println("<html><body>"); writer.println("Utente non registrato!"); writer.println("</body></html>"); writer.close(); } } }
Non sono permaloso, strivi pure senza peli sulla lingua.
Ultima modifica di giannino1995; 11-08-2018 a 19:13
Più pratica in futuro...
Tutte le implementazioni di java.util.Map hanno il containsValue(Object value) perché è già definito nella interfaccia di astrazione. Non solo TreeMap.
Se devi associare il nome utente al hash della password, se vuoi fare il lookup (ricerca dell'utente) in maniera "veloce", sarebbe meglio HashMap perché è basata su hash-table interna. TreeMap è meno veloce in questo perché organizza le entry in un albero binario "ordinato" e deve fare potenzialmente svariate comparazioni prima di arrivare a trovare la chiave.
Il vantaggio di TreeMap su HashMap è che TreeMap è una collezione "sorted", ovvero mantiene ordinate le chiavi e l'iterazione per chiave è appunto ordinata con quel tal criterio (dato da Comparable o Comparator).
E comunque, tornando al containsValue(), se il valore nella mappa fosse il solo hash, allora containsValue() NON ti serve. Tu non devi andare a cercare un hash! Ci potrebbero essere due utenti che hanno password DIVERSE ma che danno lo STESSO hash. Si chiama "collisione" negli algoritmi di hashing, ed è possibile. Ovviamente più l'algoritmo di hashing è buono e dà un hash di lunghezza maggiore ... e meno è la probabilità di collisioni.
E in quel TreeMap<Integer,String[]> la chiave (quel Integer) cosa è??
No, contorto e comunque non ti funziona. Il containsValue fa i confronti tra il valore ricevuto e i valori nella mappa usando equals(). Ma i tuoi valori sono degli array. E negli array il equals() NON è stato ridefinito, rimane quello ereditato da Object, che si basa solo sulla "identità" degli oggetti.
Quindi NON va bene. (questa cosa degli array "dovresti" già saperla).
Sono felice di aver risolto. Sapevo il discorso di containsValue(), ero a conoscenza che non si potesse usare la funzione per comparare vettori ma non me lo ricordavo più. Non uso Java da svariati mesi.
Ho risolto in questo modo ma ero anche di corsa:
ma effettivamente è un metodo lento per 2 motivi:codice:public boolean CercaUtente(TreeMap<Integer, String[]> Matrice, String[] VettoreRiga) { for (int i = 0; i < Matrice.size(); i++) { int L = VettoreRiga.length; int k = 0; for (int j = 0; j < L; j++) { if ((Matrice.get(i)[j]).equals(VettoreRiga[j])) { k++; } } if (k == L) { return true; } } return false; }
1.ci sono 2 cicli for;
2.c'è una TreeMap invece di una HashMap;
Pensi che debba riscrivere tutto usando una HashMap?
La chiave della TreeMap penso di usarla come ID perché l'utente autenticato deve aggiungere in un oggetto delle coordinate e stamparle in una pagina. Fatto ciò l'esercitazione e quasi terminata. Forse posso fare a meno dell'ID, in questo momento non ho ancora chiaro ciò di cui ho bisogno.
I tuoi aiuti sono davvero utilissimi, sei davvero gentilissimo.
ciao
Più pratica in futuro...
Questa cosa a tuo avviso è meglio?
I problemi di collisione vengono risolti da HashMap in automatico, giusto?codice:package web1; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; public class FromTxtToMatrix { private HashMap<String, String> Matrice = new HashMap<>(); public HashMap<String, String> LeggiFile(String File) throws IOException { FileReader f = new FileReader(File); BufferedReader b = new BufferedReader(f); int Riga = 0; String[] VettoreRiga; String StringaRiga = null; while (true) { StringaRiga = b.readLine(); if (StringaRiga == null) break; VettoreRiga = StringaRiga.split(","); this.Matrice.put(VettoreRiga[0], VettoreRiga[1]); } return Matrice; } public boolean CercaUtente(HashMap<String, String> Matrice, String[] VettoreRiga) { if (Matrice.containsKey(VettoreRiga[0])){ if ((Matrice.get(VettoreRiga[0])).equals(VettoreRiga[1])) { return true; } } return false; } }
La mia domanda è anche un'altra: se metto in un try/cath la sola stringa (Matrice.get(VettoreRiga[0])).equals(VettoreRiga[1]) posso risparmiare Matrice.containsKey(VettoreRiga[0])? In buona sostanza posso ancora risparmiare tempo e risorse oppure il mio codice è "perfetto"?
Grazie come sempre
Più pratica in futuro...
No
Se la chiave è lo username, non ci sono "collisioni" (non c'entra più il hash). A meno che nel file hai più volte lo stesso utente, nel qual caso l'ultimo trovato batte gli altri.
Il tuo codice è molto lontano dall'essere "perfetto". Per le denominazioni, stile, per il fatto che tieni il HashMap come variabile di istanza ma poi al CercaUtente ripassi un HashMap, ecc...
Mille grazie, ho corretto le tue classi usando le tue direttive ed i tuoi suggerimenti. Ora è tutto più ordinato.
Il problema da risolvere è quello di implementare i filtri. Hai detto che l’autenticazione deve essere implementata nella Servlet e così ho fatto. E’ giusto pensare in questo modo?
1.Nella Servlet verifico i parametri di login (già fatto) e creo la relativa sessione o verifico l’esistenza dell’utente in una sessione già attiva;
2.Nel filtro verifico l’esistenza di una sessione, se si invio l’utente alla Servlet altrimenti lo mando alla pagina di login scrivendo all’interno di essa (utente non in db o qualcosa di simile).
Ciao e grazie
Più pratica in futuro...
Il filtro deve innanzitutto verificare se c'è una sessione oppure no. Attenzione, che il filtro NON deve creare una nuova sessione se non ci fosse ancora!
Se non c'è la sessione, è inutile andare avanti, sicuramente non c'è un utente loggato. Se invece c'è la sessione, verifichi se tra i suoi attributi ce n'è uno (decidi tu quale/come) che dice che il tal utente è loggato.
Se c'è un utente loggato fai procedere la request normalmente (finirà ad una servlet, jsp o altro). Se non c'è un utente loggato, fai redirect ad una pagina di login.