Autenticazione del nome utente, password utilizzando i filtri in Java (contattando con il database)

Quanto segue è la parte del codice Java utilizzando i filtri che mostrano la pagina di errore in qualsiasi momento se il nome utente e la password sono corretti. Per favore aiutami, non ho molta conoscenza di questo concetto.

String sql="select * from reg where username='"+user+"' and pass='"+pwd+"'"; rs=st.executeQuery(sql); if(rs.next()) { chain.doFilter(request,response); } else sc.getRequestDispatcher("/error.html").forward(request,response); 

String sql = “select * from reg where username = ‘” + user + “‘ e pass = ‘” + pwd + “‘”;

Questa è una pratica estremamente negativa. Questo approccio richiede che sia il nome utente sia la password siano passati per semplice vaniglia attraverso le richieste. Inoltre, c’è un attacco di SQL injection.

Utilizza le sessioni, in JSP / Servlet per HttpSession . Non c’è nemmeno bisogno di colpire il DB ancora e ancora su ogni richiesta usando un Filter . È inutilmente costoso. Basta mettere User in sessione usando un Servlet e utilizzare il Filter per controllarne la presenza su ogni richiesta.

Inizia con un /login.jsp :

 
${error}

Quindi, creare un LoginServlet che è mappato su url-pattern di /login e ha implementato doPost() come segue:

 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = userDAO.find(username, password); if (user != null) { request.getSession().setAttribute("user", user); // Put user in session. response.sendRedirect("/secured/home.jsp"); // Go to some start page. } else { request.setAttribute("error", "Unknown login, try again"); // Set error msg for ${error} request.getRequestDispatcher("/login.jsp").forward(request, response); // Go back to login page. } 

Quindi, crea un LoginFilter che è mappato su url-pattern di /secured/* (puoi scegliere il tuo tuttavia, ad esempio /protected/* , /restricted/* , /users/* , etc, ma questo deve almeno coprire tutto pagine protette, è necessario inserire le JSP nella cartella appropriata in WebContent) e ha implementato doFilter() come segue:

 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpSession session = request.getSession(false); String loginURI = request.getContextPath() + "/login.jsp"; boolean loggedIn = session != null && session.getAttribute("user") != null; boolean loginRequest = request.getRequestURI().equals(loginURI); if (loggedIn || loginRequest) { chain.doFilter(request, response); // User is logged in, just continue request. } else { response.sendRedirect(loginURI); // Not logged in, show login page. } 

Questo dovrebbe essere. Spero che questo ti aiuti.

Per avere l’idea di come UserDAO un UserDAO , potresti trovare utile questo articolo . Inoltre, spiega come utilizzare PreparedStatement per salvare la tua webapp dagli attacchi di SQL injection.

Guarda anche:

  • Come redirect alla pagina di accesso quando la sessione è scaduta nell’applicazione Web Java?
  • Filtro di autenticazione e servlet per il login
  • Come gestire l’autenticazione / authorization con gli utenti in un database?

Utilizzare una dichiarazione preparata, il codice è un invito aperto per un’iniezione SQL .

 Connection con = getMyConnection(); try { //no string concatenation, we use ? instead: PreparedStatement ps = con.prepareStatement("select * from reg where username=? and pass=?"); try { //actual value for parameters are set here: ps.setString(1, user); ps.setString(2, pwd); ResultSet rs = ps.executeQuery(); if(rs.next()) { chain.doFilter(request,response); } else { sc.getRequestDispatcher("/error.html").forward(request,response); } } finally { ps.close(); } } finally { con.close(); } 

Ora per la tua domanda, controlla:

  • che i nomi di tabella e colonna sono quelli giusti (non hai una colonna “login” e una colonna “username”?)
  • che i valori sono veramente corretti (prova la query in sqldevelopper per esempio)
  • che funzioni con una password e un nome utente ascii-7 (potrebbe essere un problema di codifica)
  • che la colonna della password contiene la vera password e non un hash di essa

Tante cose che non vanno in questo …: – /

  1. Il più grande – SQL Injection . Non scrivere un’altra riga di SQL nel codice finché non lo capisci. E non è un’esagerazione per effetto; il codice scritto senza la comprensione di questo è in grado di fornire un accesso arbitrario al database dell’utente.
  2. Non dovresti essere in grado di inviare una query come questa perché non dovresti mai memorizzare le password in testo semplice. Invece, dovresti calcolare e memorizzare un qualche tipo di hash (preferibilmente salato) della password, quindi hash la password inviata e confrontarla. Vedi, per esempio, come memorizzare al meglio login e password utente e Salting your password here on SO. Ciò è particolarmente negativo data la vulnerabilità di SQL injection.
  3. select * from reg non è necessario dato che vuoi solo sapere se esiste una riga. Se hai usato select 1 invece il database non avrebbe dovuto ispezionare il contenuto della riga e potrebbe servire i risultati della query solo dall’indice. Se ci si aspetta che ci siano molte righe, select 1 where exists ... sarebbe più veloce in quanto ciò consentirebbe al DB di cortocircuitare la query dopo aver trovato almeno una riga.
  4. Non stai chiudendo la dichiarazione e il risultato viene impostato in blocchi alla finally . Ciò significa che non è garantito che vengano sempre eliminati (ad esempio se viene lanciata una SQLException ) che porta a perdite di risorse e connessioni.

Prima di tutto, dovresti davvero usare query parametrizzate per questo. Se l’utente immette '";DROP TABLE reg; come nome utente si sarà in grossi problemi.

Inoltre, sei sicuro che il nome utente e la password siano corretti? Che ne dici di capitalizzazione?