Creare un contavisite in Spring Boot

di il
16 risposte

Creare un contavisite in Spring Boot

Ciao a tutti,
Ho trovato a mio avviso molto bella e semplice che spiega come gestire i cookie in Spring Boot ma sembra avere due problemi:
1) ogni volta che un utente loggato oppure no naviga tra le pagine del sito obbliga l'applicazione a verificare se nel browser c'è un cookie;
2) la funzione readCookie() va aggiunta a tutti i metodi della classe contrassegnata come @Controller, non ho 100 pagine html dinamiche ma è ugualmente scomodo;
Oltre a leggere il cookie devo anche leggere l'IP, verificare la loro esistenza nel db, aggiungere record alla tabella del contavisite, contare le visite giornaliere e totali, ecc... A me piacerebbe che questo controllo del cookie, dell'IP e quindi l'interrogazione del db avvenisse una volta sola per ciascun visitatore (autenticato o meno) e non ogni volta che il client cambia pagina. La mia preoccupazione è di impegnare eccessivamente ed inutilmente il server, quindi di sprecare molte risorse.
A) Esiste una soluzione o mi devo rassegnare?
Nella guida ho visto che ci sono anche queste specifiche:

cookie.setSecure(true); // no!
cookie.setHttpOnly(true); // si!
cookie.setPath("/"); // si!
Dato che non so se implementerò o meno l'https in fase di produzione pensavo di non usare setSecure() così il mio contavisite funzionerà sia quando ho http che https. setHttpOnly() pensavo di usarlo perché mi sembra una cosa interessante anche se comunque poco utile dato che i cookie saranno identici per ogni client. setPath("/") pensavo di usarlo perché il cookie che creo nella pagina 'benvenuto.html' deve essere leggibile dal server anche nella pagina 'mozzarelle.html', ecc...
B) Concordate o avete altri suggerimenti?

16 Risposte

  • Re: Creare un contavisite in Spring Boot

    Beh ma dipende da cosa vuoi fare esattamente. Un "conta visite" .. ok. Ma considerando le visite COME?

    - intese come richieste distinte, singole per ciascuna pagina? (qui i cookie non c'entrerebbero affatto!)
    - intese come singola "navigazione" di un utente? (qui sì, i cookie possono servire)

    E vuoi cercare di non contare (il più e per quanto possibile) l'accesso da parte di qualunque crawler/spider (GoogleBot, ecc...) oppure no?

    E comunque un buon hosting ti mette GIÀ a disposizione tutta una serie di report e grafici sulle statistiche di utilizzo da parte degli utenti (pure, per dire, le percentuali di utilizzo in base ai vari browser o la nazionalità degli utenti).

    Temo che stai cercando di fare "troppe" cose .... e così non vai avanti ...
  • Re: Creare un contavisite in Spring Boot

    Non è detto che l'hosting fornisca queste funzionalità ma al contempo non sembra una cosa complessa da fare. Avere in una pagina il numero di visite totali e giornaliere non mi spiace affatto.
    A me interessa ottenere il numero di visite uniche che riceve il mio dominio, se una pagina riceve più visite di un'altra non mi importa. Il cookie può essere rimosso, l'ip può cambiare ma se li considero entrambi la bontà della mia stima aumenta. I crawler/spider (GoogleBot, ecc...) penso di trattarli come semplici client, registro il loro ip e se posso salvo sulle loro piattaforme un cookie.
    Esempio:
    Se il mio contavisite è a 234 e 'Marco Rossi' residente a Bologna in Via Della Fornula 45 accede al mio sito il 2/10/2021 e visita 3 pagine poi ritorna dopo 1 settimana e rivisita altre 2 pagine più una nuova che nel frattempo ho aggiunto, dopo dutte queste n visite la mia tabella dovrà contenere 235 record e le visite dovranno appunto essere 235.
    E' chiaro che qualche errore lo farò nella mia misurazione ma se registro ip ed uso un cookie unico per tutti i client la probabilità che commetta un errore è minima.
    Quello che mi piacerebbe fare è lanciare le query verso il db e fare le mie considerazioni non appena 'Marco Rossi' accede ad una pagina qualsiasi e soprattutto una volta sola, non ripetutamente ogni volta che il client cambia pagina.
    Per gestire l'accesso ad una pagina qualsiasi sai se una cosa di questo tipo possa funzionare?
    
    @RequestMapping(value = "/*", method = RequestMethod.GET)
    ... il metodo che fa i dovuti calcoli e lancia le dovute query ...
    @RequestMapping(value = "/*", method = RequestMethod.POST)
    ... il metodo che fa i dovuti calcoli e lancia le dovute query ...
    
    C'è modo di aggiungere qualche cosa per non richiamare continuamente questo metodo ogni volta che il client cambia pagina?
    Non c'è la possibilità di disporre di qualche 'variabile di sessione'?
    Cambiare pagina alla webapp oppure chiudere il browser ed accedere ad una nuova pagina non penso sia la stessa cosa per il server, nel primo caso il client resto lo stesso, nel secondo i client sono 2.
    Può funzionare?
    
            // Creazione di una variabile di sessione
            String client = "client-generico";
            session.setAttribute("client", client);
            // Recupero di una variabile di sessione
            String client = session.getAttribute("client");
    
    Questo è il mio db:
    
    CREATE TABLE IF NOT EXISTS contavisite (
        id BIGSERIAL NOT NULL,
        ip VARCHAR(39) NOT NULL,
        data_ora TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        CONSTRAINT contavisite_pk PRIMARY KEY(id),
        CONSTRAINT contavisite_uk UNIQUE (ip)
    );
    
  • Re: Creare un contavisite in Spring Boot

    Ecco cosa ho in mente:
    
        // Questo metodo viene utilizzato per gestire il contavisite.
        @RequestMapping(value = "/*", method = RequestMethod.GET)
        public void gestioneContavisiteGet(HttpSession session){
            try{
                if(session.getAttribute("client").equals("presente")){
                    System.out.println("non faccio nulla...");
                }else {
                    session.setAttribute("client", "presente");
                    System.out.println("client non registrato, avvio il metodo della classe x, interrogo il db, ecc...");
                }
            }catch (Exception e){
                System.out.println("qualcosa è andato storto...");
            }
        }
    
        // Questo metodo viene utilizzato per gestire il contavisite.
        @RequestMapping(value = "/*", method = RequestMethod.POST)
        public void gestioneContavisitePost(){
            try{
    
            }catch (Exception e){
    
            }
        }
    
    (ovviamente non funziona...)
  • Re: Creare un contavisite in Spring Boot

    La cosa più bella sarebbe poter usare una classe separata e fare tutto qui dentro:
    
    public class ConteggioVisiteSito {
    
        public void gestioneContavisite(HttpSession session){
            System.out.println("ciao");
            try{
                if(session.getAttribute("client").equals("presente")){
                    System.out.println("non faccio nulla...");
                }else {
                    session.setAttribute("client", "presente");
                    System.out.println("client non registrato, avvio il metodo della classe x, interrogo il db, ecc...");
                }
            }catch (Exception e){
                System.out.println("qualcosa è andato storto...");
            }
        }
    
    }
    
    Ho provato con diverse annotazioni ma non ho risolto.
  • Re: Creare un contavisite in Spring Boot

    iBaffiPro ha scritto:


    Non è detto che l'hosting fornisca queste funzionalità
    La maggior parte sì ... a meno che ne trovi uno così "patetico" che non ti offre nulla del genere e per chissà quale prezzo ....
    Poi comunque queste statistiche/report sono intese generalmente solo per il proprietario del sito ... non per chiunque. Quindi non sono esposte ai visitatori, ecc...
    Se invece vuoi mostrare un numerino nelle pagine, no, devi implementarlo tu.

    iBaffiPro ha scritto:


    non sembra una cosa complessa da fare. Avere in una pagina il numero di visite totali e giornaliere non mi spiace affatto.
    A me interessa ottenere il numero di visite uniche che riceve il mio dominio, se una pagina riceve più visite di un'altra non mi importa. Il cookie può essere rimosso, l'ip può cambiare ma se li considero entrambi la bontà della mia stima aumenta. I crawler/spider (GoogleBot, ecc...) penso di trattarli come semplici client, registro il loro ip e se posso salvo sulle loro piattaforme un cookie.
    "sembra" facile ....

    Considera anche che se ci sono 100 utenti dietro es. una rete aziendale e visitano il tuo sito, vedrai lo stesso IP per tutti quanti ... quello "pubblico" della loro connessione a internet.

    iBaffiPro ha scritto:


    
    @RequestMapping(value = "/*", method = RequestMethod.GET)
    ... il metodo che fa i dovuti calcoli e lancia le dovute query ...
    @RequestMapping(value = "/*", method = RequestMethod.POST)
    ... il metodo che fa i dovuti calcoli e lancia le dovute query ...
    
    Questo non ti può funzionare. La risoluzione degli url sceglie il mapping "più specifico". Quindi tra un @RequestMapping "/*" e uno "/pippo", se il client chiede /pippo, verrà invocato solo il secondo.

    In Spring/Boot esistono gli Interceptor, studiali.
    E ci sono anche i Filter di JavaEE.
  • Re: Creare un contavisite in Spring Boot

    Se dietro un IP ci sono 100 utenti pazienza, non è un problema. Potrebbe anche capitare, caso forse addirittura più probabile, che 100 utenti da smartphone si colleghino al mio sito tramite il Wi-Fi di un internet cafè. Potrebbe anche capitare che un utente cancelli i cookie e si riconnetta al sito settimane dopo con un IP diverso perché il provider glielo ha cambiato oppure perché ha cambiato operatore, ecc... A tutto ciò dico pazienza! Il numero che otterrò sarà sbagliato ma la sua variazione nel tempo mi potrà essere utile.

    Forse ho trovato una soluzione ma non funziona alla perfezione perché quando un utente preme su logout, anche senza riavviare il browser il server vede un nuovo client e quindi nel mio caso riesegue una nuova interrogazione del db con il conseguente spreco di risorse. Anche a questo inconveniente dico pazienda, il cambio pagina è sicuramente più frequente del login e del logout. Altro inconveniente ben più grave ma che non capisco perché accade si verifica quando sul mio pc provo ad aprire una sessione su chrome e poi una su mozilla. Non appena apro la sessione su mozilla l'ide mi segnala degli errori:
    
    creo la sessione
    conteggio la visita
    creo la sessione
    conteggio la visita
    2021-10-02 22:02:42.807 ERROR 13936 --- [io-8443-exec-10] org.apache.tomcat.util.net.NioEndpoint   : Error running socket processor
    
    Dovrei sostituire questo "client" con una chiave sempre diversa?

    La soluzione che avrei dovuto scriverti in testa al messaggio, perdona il disordine, è la seguente:
    
            try{
                if(!(session.getAttribute("client")!=null && session.getAttribute("client").equals("presente"))){
                    System.out.println("creo la sessione");
                    session.setAttribute("client", "presente");
                    System.out.println("conteggio la visita");
                }
            }catch (Exception e){
                session.setAttribute("client", "presente");
            }
    
    Se vuoi puoi farmi un esempio di Interceptor. Con i filtri credo che il problema che otterrei sarebbe identico. Ho visto che Spring Boot permette anche la creazione di sessioni trasversali separate da quelle HTML ma non saprei come gestirle, mi servirebbe un esempio concreto da cui partire.

    P.S.: Il codice
    System.out.println("conteggio la visita");
    verrà ovviamente sostituito dal famoso metodo che aggiungerà l'ip al database o lo aggiornerà, verificherà la presenza di un cookie o lo creerà, ecc...
  • Re: Creare un contavisite in Spring Boot

    P.S.: Ora l'errore non compare più... boh...
  • Re: Creare un contavisite in Spring Boot

    iBaffiPro ha scritto:


    Non appena apro la sessione su mozilla l'ide mi segnala degli errori:
    
    2021-10-02 22:02:42.807 ERROR 13936 --- [io-8443-exec-10] org.apache.tomcat.util.net.NioEndpoint   : Error running socket processor
    
    Se cerchi in rete NioEndpoint : Error running socket processor
    scoprirai che si tratta di un bug del runtime Java legato al SSL/TLS.

    iBaffiPro ha scritto:


    La soluzione che avrei dovuto scriverti in testa al messaggio, perdona il disordine, è la seguente:
    
            try{
                if(!(session.getAttribute("client")!=null && session.getAttribute("client").equals("presente"))){
                    System.out.println("creo la sessione");
                    session.setAttribute("client", "presente");
                    System.out.println("conteggio la visita");
                }
            }catch (Exception e){
                session.setAttribute("client", "presente");
            }
    
    Scritto così non ha molto senso. Se puoi accedere a quel reference session ... vuol dire che la sessione c'è già, quindi che senso ha nel if "creo la sessione" ?

    E comunque quel if andrebbe riscritto (senza la negazione di tutto, che è meno facile da leggere). E anche quel catch è da vedere il senso/utilità ...

    iBaffiPro ha scritto:


    Se vuoi puoi farmi un esempio di Interceptor.
    Devi prima comprendere: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-handlermapping-interceptor

    iBaffiPro ha scritto:


    Ho visto che Spring Boot permette anche la creazione di sessioni trasversali separate da quelle HTML
    A che ti riferisci esattamente?

    iBaffiPro ha scritto:


    P.S.: Il codice
    System.out.println("conteggio la visita");
    verrà ovviamente sostituito dal famoso metodo che aggiungerà l'ip al database o lo aggiornerà, verificherà la presenza di un cookie o lo creerà, ecc...
    Inizia a fare le cose "semplici": conteggio puntuale delle visite di ciascuna singola pagina. Niente cookie, niente sessioni.
    Fai una tabella con id, path (del url, dalla server-root), contatore e data_agg (non fondamentale ma utile).
    E gestiscilo tramite Interceptor. L'Interceptor dovrà determinare il path della pagina, effettuare l'incremento del conteggio e poi settare nel request-scope il valore che una qualunque view potrà poi visualizzare.
    Poi bisogna comunque vedere COME hai fatto le view, se hai tante view distinte (struttura "copiata") oppure se hai adottato una sorta di templating per cui ad esempio hai un footer "comune", che ovviamente semplifica molto le cose.

    Qualunque altra ottimizzazione la puoi fare dopo. Dimentica statistiche "sofisticate" tipo percentuali di utilizzo dei vari browser o la nazionalità degli utenti. Queste sono cose più complesse e che richiedono altre nozioni e "risorse".
    Se non riesci a fare una cosa semplice come quanto detto, è poi difficile aiutarti su cose più particolari/avanzate....
  • Re: Creare un contavisite in Spring Boot

    Grazie per il tuo intervento. Se vuoi postare un codice provo a vedere se riesco a complenderlo. Dalla pagina che riporti non mi viene in mente nulla. Sembrano cose complicate, non so se sono alla mia portata.
    Comunque il mio metodo creaSessione() funziona perché lancia il metodo conta() una volta sola.
    
        public void creaSessione(HttpSession session, HttpServletRequest request, HttpServletResponse response){
            try{
                if(!(
                        session.getAttribute(nomeVariabileDiSessione)!=null &&
                        session.getAttribute(nomeVariabileDiSessione).equals(attributoVariabileDiSessione)
                )){
                    session.setAttribute(nomeVariabileDiSessione, attributoVariabileDiSessione);
                    conta(request, response);
                }
            }catch (Exception e){
                conta(request, response);
            }
        }
    
    I cookie riesco a crearli, verificarne l'esistenza e cancellarli con tutti i browser.
    Gli IP riesco ad individuarli con tutti i browser tranne che con Mozilla.
    In realtà trovo l'IP anche con Mozilla ma il formato è IPv4 e non riesco a convertirlo in IPv6 in nessun modo:
    Con Chrome, Opera, Edge, IE ottengo:
    0:0:0:0:0:0:0:1
    Con Mozilla:
    127.0.0.1
    Ho provato ad importare questa libreria e a perfezionare il mio metodo ma non risolvo:
    
    		<dependency>
    			<groupId>com.github.seancfoley</groupId>
    			<artifactId>ipaddress</artifactId>
    			<version>5.3.3</version>
    		</dependency>
    
    Con Chrome, Opera, Edge, IE ottengo:
    0000:0000:0000:0000:0000:0000:0000:0001
    Con Mozilla:
    0000:0000:0000:0000:0000:ffff:7f00:0001
    Ecco il codice:
    
        public String ipDelClient(){
            try{
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .getRequest();
                String ipDelClient = request.getRemoteAddr();
                if(ipDelClient!=null && !ipDelClient.isEmpty()){
                    IPAddress address = new IPAddressString(ipDelClient).getAddress();
                    IPv6Address ipv6Address = address.toIPv6();
                    return String.valueOf(ipv6Address.toFullString());
                }else{
                    return "";
                }
            }catch (Exception e){
                return "";
            }
        }
    
    Sapresti suggerirmi un metodo per determinare l'ip in modo univoco ed ovviamente IPv6?
    Per quando riguarda l'errore strano ho letto che aggiornando a 11.0.12 risolvo ma non ho ancora avuto tempo a provare perché sono concentrato su questo ip maledetto. Al momento sto usando 11.0.11. Speriamo in bene...
    https://www.oracle.com/java/technologies/downloads/#java11
  • Re: Creare un contavisite in Spring Boot

    iBaffiPro ha scritto:


    Grazie per il tuo intervento. Se vuoi postare un codice provo a vedere se riesco a complenderlo. Dalla pagina che riporti non mi viene in mente nulla. Sembrano cose complicate, non so se sono alla mia portata.
    Posso anche provare a mettere giù un esempio ma dovrei poi comunque "contestualizzarlo" bene .. altrimenti si capirebbe poco. Vedo ...
    Ma ad ogni modo: se trovi questi aspetti (interceptor ecc...) "ostici", allora come dici forse non sono (ancora) alla tua portata. Quindi potresti magari lasciare perdere tutta questa logica dei contatori (?)

    iBaffiPro ha scritto:


    Ho provato ad importare questa libreria e a perfezionare il mio metodo ma non risolvo:
    
    		<dependency>
    			<groupId>com.github.seancfoley</groupId>
    			<artifactId>ipaddress</artifactId>
    			<version>5.3.3</version>
    		</dependency>
    
    Non ho idea di cosa sia e faccia effettivamente .... posso andare a vedere più tardi ..

    iBaffiPro ha scritto:


    Sapresti suggerirmi un metodo per determinare l'ip in modo univoco ed ovviamente IPv6?
    Non capisco perché ti stai ostinando con questi IP. L'indirizzo IP in un contesto di statistiche come questo è solo "documentativo". Non ti può servire per distinguere davvero gli utenti. Lo puoi usare ad esempio in una tabella che logga la data-ora di un accesso o poco altro.
    E non vedo cosa ti cambia tra IPv4 e IPv6. È una stringa e basta ...
  • Re: Creare un contavisite in Spring Boot

    L'IP da solo non serve a nulla ma se lo si associa ad un cookie con un nome univoco ed una chiave sempre diversa si riesce a monitorare molto bene il traffico sul proprio sito.
    Lavorare con IPv4 oppure con IPv6 cambia e anche parecchio, rischio di registrare a database 2 record per un solo IP (per esmpio basta che l'utente si connetta con Chrome e poi con Mozilla).
    Comunque questo Spring Boot fa acqua da tutte le parti. Il mio codice è perfetto ed i problemi sono tanti:
    1) Su Mozilla il mio IP è il seguente:
    0000:0000:0000:0000:0000:ffff:7f00:0001
    invece di questo:
    0000:0000:0000:0000:0000:0000:0000:0001
    2) Il metodo per cercare un cookie non funziona. Il cookie è presente nel browser ma non viene trovato.
    Ecco il mio progettino (come vedi è molto semplice la cosa che sto facendo, non mi interessa neppure differenziare le visite per pagine diverse):
    
    CREATE TABLE IF NOT EXISTS contavisite (
        id BIGSERIAL NOT NULL,
        ip VARCHAR(39) NOT NULL,
        data_ora TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        CONSTRAINT contavisite_pk PRIMARY KEY(id),
        CONSTRAINT contavisite_uip UNIQUE (ip)
    );
    
    
    @Controller
    public class ControlloPagineWeb {
    
        // ...
    	
        public void variabiliGeneraliPerPaginaHTML(
                Principal principal, 
                Model model, 
                HttpSession session,
                HttpServletRequest request,
                HttpServletResponse response
        ){
    		// ...
            try{
                ConteggioVisiteSito conteggioVisiteSito = new ConteggioVisiteSito(session, request, response);
            }catch (Exception e){
                // System.out.println("Impossibile eseguire il conteggio delle visite.");
            }
    		// ...
        }
    
        @RequestMapping(value = { "/", "/benvenuto" }, method = RequestMethod.GET)
        public String paginaBenvenuto(
                Model model, 
                Principal principal, 
                HttpSession session, 
                HttpServletRequest request, 
                HttpServletResponse response
        ) {
            variabiliGeneraliPerPaginaHTML(principal, model, session, request, response);
            model.addAttribute("titolo", "Benvenuto!");
            model.addAttribute("messaggio", "Benvenuto!");
            return "index";
        }
    
    	// ...
    
    }
    
    
    // Questa classe esegue il conteggio delle visite ricevute dal sito.
    public class ConteggioVisiteSito {
    
        private final String nomeCookie = "clientSuGestioneUtenti";
        private final String nomeVariabileDiSessione = "clientSuGestioneUtenti";
        private final String attributoVariabileDiSessione = "presente";
    
        public ConteggioVisiteSito() {
        }
    
        public ConteggioVisiteSito(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
            creaSessione(session, request, response);
        }
    
        public void creaSessione(HttpSession session, HttpServletRequest request, HttpServletResponse response){
            try{
                if(!(
                        session.getAttribute(nomeVariabileDiSessione)!=null &&
                        session.getAttribute(nomeVariabileDiSessione).equals(attributoVariabileDiSessione)
                )){
                    session.setAttribute(nomeVariabileDiSessione, attributoVariabileDiSessione);
                    conta(request, response);
                }
            }catch (Exception e){
                conta(request, response);
            }
        }
    
        public void conta(HttpServletRequest request, HttpServletResponse response){
            try{
                System.out.println("");
                System.out.println("");
                System.out.println("");
                System.out.println("conteggio la visita");
                creaCookie(response,nomeCookie,String.valueOf(1));
                System.out.println(cercaCookie(request,nomeCookie,String.valueOf(1)));
                System.out.println(cercaCookie(request,nomeCookie,String.valueOf(2)));
                System.out.println(cercaCookie(request,"h",String.valueOf(1)));
                System.out.println(cercaCookie(request,"h",String.valueOf(10)));
                cancellaCookie(response,nomeCookie);
                System.out.println(ipDelClient());
                System.out.println(ipDelServer());
            }catch (Exception e){
                // System.out.println("Impossibile eseguire il conteggio delle visite.");
            }
        }
    
        public boolean cercaCookie(HttpServletRequest request, String nomeCookie, String valoreCookie){
            try{
                Cookie[] cookies = request.getCookies();
                for(int i=0; i<cookies.length; i++){
                    if(cookies[i].getName().equals(nomeCookie) && cookies[i].getValue().equals(valoreCookie)){
                        return true;
                    }
                }
                return false;
            }catch (Exception e){
                return false;
            }
        }
    
        public void creaCookie(HttpServletResponse response, String nomeCookie, String valoreCookie){
            try{
                Cookie cookie = new Cookie(nomeCookie, valoreCookie);
                int secondi = 2147483647;
                cookie.setMaxAge(secondi);
                cookie.setHttpOnly(true);
                cookie.setPath("/");
                response.addCookie(cookie);
            }catch (Exception e){
                // System.out.println("Impossibile eseguire il conteggio delle visite.");
            }
        }
    
        public void cancellaCookie(HttpServletResponse response, String nomeCookie){
            try{
                Cookie cookie = new Cookie(nomeCookie, null);
                int secondi = 0;
                cookie.setMaxAge(secondi);
                cookie.setHttpOnly(true);
                cookie.setPath("/");
                response.addCookie(cookie);
            }catch (Exception e){
                // System.out.println("Impossibile eseguire il conteggio delle visite.");
            }
        }
    
        public String ipDelClient(){
            try{
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .getRequest();
                return fromIPv4ToIPv6(request.getRemoteAddr());
            }catch (Exception e){
                return "";
            }
        }
    
        public String ipDelServer(){
            try{
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .getRequest();
                return fromIPv4ToIPv6(request.getLocalAddr());
            }catch (Exception e){
                return "";
            }
        }
    
        public String fromIPv4ToIPv6(String IPv4){
            try{
                if(IPv4!=null && !IPv4.isEmpty()){
                    IPAddress address = new IPAddressString(IPv4).getAddress();
                    IPv6Address ipv6Address = address.toIPv6();
                    String IPv6 = String.valueOf(ipv6Address.toFullString());
                    return IPv6;
                }else{
                    return "";
                }
            }catch (Exception e){
                return "";
            }
        }
    
    }
    
  • Re: Creare un contavisite in Spring Boot

    iBaffiPro ha scritto:


    L'IP da solo non serve a nulla ma se lo si associa ad un cookie con un nome univoco ed una chiave sempre diversa si riesce a monitorare molto bene il traffico sul proprio sito.
    Nì ... comunque se per te ok .. ok.

    iBaffiPro ha scritto:


    Lavorare con IPv4 oppure con IPv6 cambia e anche parecchio, rischio di registrare a database 2 record per un solo IP (per esmpio basta che l'utente si connetta con Chrome e poi con Mozilla).
    Ma cosa succede in locale, con browser e server sulla TUA stessa macchina, non ha alcuna particolare importanza!
    Quello che poi conta (conterà) è il IP "pubblico" che si ha su internet.
    Al momento sono a casa, il mio provider mi sta dando un ip 95.xxx.xxx.xxx ed ho solo il IPv4 su internet, il IPv6 è disabilitato (forse nemmeno supportato (?) non lo so). Ed è lo stesso IP, che io usi Firefox, Chrome, il mio iPad, il mio LG G6 ecc... QUESTO conta.

    iBaffiPro ha scritto:


    Comunque questo Spring Boot fa acqua da tutte le parti.
    Aridaje .... aho ..
    E gli interceptor ti sono ostici ... e quell'altra cosa ti è ostica ....

    iBaffiPro ha scritto:


    Il mio codice è perfetto ed i problemi sono tanti:
    Non ho letto tutto bene ma già questo è "dubbio".
                creaCookie(response,nomeCookie,String.valueOf(1));
                System.out.println(cercaCookie(request,nomeCookie,String.valueOf(1)));
    Se crei un cookie NON ce l'hai già subito! La creazione del cookie la fai sulla response. Mentre il getCookies() lo fai sulla request.
    Prima crei il cookie che va in response, POI arriva al client e alle request SUCCESSIVE il server se lo trova nella request.
    Anche questo è "ostico"? ...
  • Re: Creare un contavisite in Spring Boot

    1) Se hai idee migliori per il conteggio delle visite sono tutto orecchie ma non ho altri strumenti oltre ad IP e cookie.
    2) Per quanto riguarda l'IP potrebbe darsi che Firefox usi IPv4 e gli altri browser IPv6.
    Se aggiungo al file .properties:
    server.address=0000:0000:0000:0000:0000:0000:0000:0001
    Tutto si mette a funzionare, anche con Firefox ma l'IDE non apre più automaticamente il browser, lo devo fare io manualmente (un bug dell'IDE? mah...).
    Se vado qui:
    https://www.vultr.com/resources/ipv4-converter/?ip_address=127.0.0.1
    ottengo lo stesso valore errato che ottengo senza la specifica server.address quindi la mia dipendenza funziona. Sono sempre più confuso...
    Ma quindi 0000:0000:0000:0000:0000:ffff:7f00:0001 è la conversione esatta di 127.0.0.1?
    0000:0000:0000:0000:0000:0000:0000:0001 e 127.0.0.1 sono 2 indirizzi IP diversi?
    A rigor di logica sembrerebbe che 0000:0000:0000:0000:0000:0000:0000:0001 debba coincidere con 0.0.0.1 ma questo non accade:
    https://www.vultr.com/resources/ipv4-converter/?ip_address=0.0.0.1
    Mi illumini? Sono sempre più confuso...
    Anche qui da me se uso dispositivi e browser diversi ottengo lo stesso IP. Il mio provider fornisce IPv4 come il tuo.
    3) Verissimo! bravo! Infatti se non cancello il cookie subito le volte sucessive che lancio l'applicazione tutto funziona. Come si aggiorna la variabile request all'interno di conta()? Si può fare?
    4) Ho trovato questa pagina:
    https://fullstackdeveloper.guru/2020/07/13/how-to-log-ip-addresses-of-incoming-requests-to-a-spring-boot-app-in-a-centralized-way/
    Si avvicina a quello che hai in mente tu?
    Con gli interceptor cosa avrebbe in più la mia applicazione?
    Sempre grazie
  • Re: Creare un contavisite in Spring Boot

    iBaffiPro ha scritto:


    1) Se hai idee migliori per il conteggio delle visite sono tutto orecchie ma non ho altri strumenti oltre ad IP e cookie.
    L'idea "semplice" l'avevo già detta in precedenza: un semplice conteggio per ciascun accesso puntuale ad una pagina. Niente IP, niente cookie, niente sessioni.

    iBaffiPro ha scritto:


    2) Per quanto riguarda l'IP potrebbe darsi che Firefox usi IPv4 e gli altri browser IPv6.
    Se aggiungo al file .properties:
    server.address=0000:0000:0000:0000:0000:0000:0000:0001
    Tutto si mette a funzionare, anche con Firefox ma l'IDE non apre più automaticamente il browser, lo devo fare io manualmente (un bug dell'IDE? mah...).
    Se vado qui:
    https://www.vultr.com/resources/ipv4-converter/?ip_address=127.0.0.1
    ottengo lo stesso valore errato che ottengo senza la specifica server.address quindi la mia dipendenza funziona. Sono sempre più confuso...
    Ma quindi 0000:0000:0000:0000:0000:ffff:7f00:0001 è la conversione esatta di 127.0.0.1?
    0000:0000:0000:0000:0000:0000:0000:0001 e 127.0.0.1 sono 2 indirizzi IP diversi?
    A rigor di logica sembrerebbe che 0000:0000:0000:0000:0000:0000:0000:0001 debba coincidere con 0.0.0.1 ma questo non accade:
    https://www.vultr.com/resources/ipv4-converter/?ip_address=0.0.0.1
    Mi illumini? Sono sempre più confuso...
    L'indirizzo di loopback in IPv4 è 127.0.0.1 e in IPv6 è ::1 che è l'abbreviazione di 0000:0000:0000:0000:0000:0000:0000:0001

    0000:0000:0000:0000:0000:0000:7f00:0001 è un IPv6 definito IPv4-Compatible ma è il modo "vecchio" che se non sbaglio è pure deprecato e non si dovrebbe usare.

    0000:0000:0000:0000:0000:ffff:7f00:0001 è un IPv6 definito IPv4-Mapped ed è la forma nuova/corretta che si dovrebbe usare ed è appunto equivalente al 127.0.0.1 in IPv4. Insomma è anch'esso il loopback.

    Prova questo:
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class ProvaIP {
        public static void main(String[] args) throws UnknownHostException {
            String[] ips = {
                    "0000:0000:0000:0000:0000:0000:0000:0001",
                    "0000:0000:0000:0000:0000:ffff:7f00:0001",
                    "0000:0000:0000:0000:0000:0000:7f00:0001",
            };
    
            for (String ip : ips) {
                InetAddress addr = InetAddress.getByName(ip);
                System.out.println(ip);
                System.out.printf("  %s%n", addr.getClass());
                System.out.printf("  loopback? %s%n", addr.isLoopbackAddress());
            }
        }
    }
    I primi due sono riconosciuti come "loopback". Il terzo no.
    E nota che il secondo è un Inet4Address perché un è IPv6 fatto come IPv4-Mapped.

    iBaffiPro ha scritto:


    3) Verissimo! bravo! Infatti se non cancello il cookie subito le volte sucessive che lancio l'applicazione tutto funziona. Come si aggiorna la variabile request all'interno di conta()? Si può fare?
    Scusa ma la domanda/questione ha poco senso. L'ho detto prima come funzionano i cookie: il cookie lo devi creare e inviare in response. Poi nelle request seguenti, verrà rimandato al server. Questo permette al server di riconoscere che c'è una "connessione" tra le request. Quindi devi ragionare proprio su questa semantica d'uso.

    iBaffiPro ha scritto:


    4) Ho trovato questa pagina:
    https://fullstackdeveloper.guru/2020/07/13/how-to-log-ip-addresses-of-incoming-requests-to-a-spring-boot-app-in-a-centralized-way/
    Si avvicina a quello che hai in mente tu?
    Sì, quello è un interceptor Spring. Io però farei la implementazione di WebMvcConfigurer in una classe @Configuration o comunque (@Component o @Configuration che sia) messa in un sotto-package "config" perché di fatto è una configurazione.

    iBaffiPro ha scritto:


    Con gli interceptor cosa avrebbe in più la mia applicazione?
    Che non devi "mescolare" la logica dei contatori in mezzo a tutti i vari controller.
Devi accedere o registrarti per scrivere nel forum
16 risposte