Reset password link in java

Hiten picture Hiten · Oct 21, 2016 · Viewed 11.3k times · Source

I am currently implementing a forgot password function in a Java project. my methodology is,

  1. User clicks the forgot password link.

  2. In the forgot password page, system prompts the user to enter the email
    address he/she has registered in to the system.

  3. Email which includes the given email address with reset password page link.

  4. User clicks the link and he/she get redirected to a page(reset password) where user can enter his new password.

  5. In Reset Password page, the field "email address" is filled automatically
    and it cannot be changed because its disabled.

    Then user enter his new password and the field related to the email address in the database is updated.

I tried this in my code but in my reset password page I didnt get the email id of the user who wants to change the password.

MailUtil.java

package com.example.controller;

import java.io.IOException;
import java.security.Security;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import com.example.util.Database;

public class MailUtil {
    private static final String USERNAME = "[email protected]";
    private static final String PASSWORD = "test";
    private static final String SUBJECT = "Reset Password link";

    private static final String HOST = "smtp.gmail.com";
    private static final String PORT = "465";

    String email;

    public MailUtil() {
    // TODO Auto-generated constructor stub
    email = this.email;
}

    public boolean sendMail(String to, HttpServletRequest request) throws SQLException, ServletException, IOException{
        Connection conn = Database.getConnection();
        Statement st = conn.createStatement();
        String sql = "select * from login where email = '" + to + "' ";
        ResultSet rs = st.executeQuery(sql);
        String pass = null;
        String firstName = null;
        while(rs.next()){
            pass = rs.getString("pass");
            firstName = rs.getString("firstName");
        }

        if(pass != null){
            setEmailId(to);         
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            Properties props = new Properties();
            props.put("mail.smtp.host", HOST);
            props.put("mail.stmp.user", USERNAME);
            //  If you want you use TLS
            //props.put("mail.smtp.auth", "true");

            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.password", PASSWORD);
            //  If you want to use SSL
            props.put("mail.smtp.port", PORT);
            props.put("mail.smtp.socketFactory.port", PORT);
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.auth", "true");

            Session session = Session.getInstance(props, new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    String username = USERNAME;
                    String password = PASSWORD;
                    return new PasswordAuthentication(username, password);
                }
            });

            String from = USERNAME;
            String subject = SUBJECT;
            MimeMessage msg = new MimeMessage(session);
            try{
                msg.setFrom(new InternetAddress(from));
                InternetAddress addressTo = new InternetAddress(to);
                msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
                msg.setSubject(subject);                
                String vmFileContent = "Hello User, <br><br> Please Click <a href='http://192.168.15.159:8080/SampleLogin/new-password.jsp><strong>here</strong></a> to reset your password. <br><br><br> Thanks,<br>ProAmbi Team";

                //  Send the complete message parts
                msg.setContent(vmFileContent,"text/html");
                Transport transport = session.getTransport("smtp");
                transport.send(msg);

                System.out.println("Sent Successfully");
                return true;
            }catch (Exception exc){
                System.out.println(exc);
                return false;
            }
        }else{
            //System.out.println("Email is not registered.");
            request.setAttribute("errorMessage", "User with this email id doesn't exist.");         
            return false;
        }
    }

    public String getEmailID() {
        return email;
    }
    public void setEmailId(String email) {
        this.email = email;
    }
}

And My new-password.jsp.

<%
    MailUtil mail = new MailUtil();
    String email = mail.getEmailID();
    System.out.println("---> "+email);
%>

But I got the null value rather than email id.

Can you pleas help me the solve this problem or get any other option to do this.

Answer

Ivan Lymar picture Ivan Lymar · Oct 21, 2016

I would advice u to use JWT token - https://jwt.io/

 public String createToken( Email mail )
  {
      Claims claims = Jwts.claims().setSubject( String.valueOf( mail.getId() ) );
        claims.put( "mailId", mail.getId() );
        Date currentTime = new Date();
        currentTime.setTime( currentTime.getTime() + tokenExpiration * 60000 );
        return Jwts.builder()
          .setClaims( claims )
          .setExpiration( currentTime )
          .signWith( SignatureAlgorithm.HS512, salt.getBytes() )
          .compact();
  }

This code will return you token string representation. So u will send the email message with this token e.g.:

"You had requested password changing. Please click this link to enter new password"

http://yourapp.com/forgotPassword/qwe213eqwe1231rfqw

Then on loaded page u will get token from request, encode it and get what ever u want.

public String readMailIdFromToken( String token )
  {
    Jwts.parser().setSigningKey( salt.getBytes() ).parseClaimsJws( token ).getSignature();
    Jws<Claims> parseClaimsJws = Jwts.parser().setSigningKey( salt.getBytes() ).parseClaimsJws( token );        
    return parseClaimsJws.getBody().getSubject();
  }

Expiration will make your token invalid if specified time has passed. Salt could be replaced with any kind of String, you could read details at JWT documentation. This approach also could be used for registartion confiramtion emails.

p.s.

1) Do not use scriplets (java code at jsp), use jstl instead

2) Do not use string concatenation in sql queries. It's dangerous. Use prepared statement instead.

3) For such info like HOST/PASSWORD e.t.c. use property files

4) Remove code which calls DB to appropriate DAO. (u should read about DAO pattern)

5) Do not use system.out.println at your code at all. Use any kind of logger.

useful links:

https://jstl.java.net/

https://en.wikipedia.org/wiki/SQL_injection

https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html

https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

https://en.wikipedia.org/wiki/Multitier_architecture