3
votes

I am trying to create a login action on my web page, which is supposed to call a servlet passing it the required parameters, and return a JSON object to the browser. I am using the $.getJSON() method from jQuery for this purpose.

Here is the HTML for my login form-

<form class="form" method="post" id="loginFrm" name="loginFrm">
    <div class="form-group">
       <label for="username">Email</label>
             <input name="email" id="email" type="text" placeholder="Email" style="color: black;">
                                </div>
         <div class="form-group">
            <label for="password">Password</label>
            <input name="password" id="password" type="password" placeholder="Password" style="color: black;"><br>
         <span class="text-danger" id="error-box"></span>
    </div>
       <button id="btnLogin" class="btn btn-primary" style="margin-top: 17px;">Login</button>
 </form>

Here is the JavaScript code that executes on clicking upon the login button-

// Add an onlick handler to the login button
$('#btnLogin').on('click', loginAction);


function loginAction()  {
var userEmail = $('#email').val();
var userPassword = $('#password').val();

if (userEmail == "")    {
    $('#error-box').html("Please enter your email");
    $('#email').focus();
    return false;
}

if (userPassword == "") {
    $('#error-box').html("Please enter your password");
    $('#password').focus();
    return false;
}

var credentials = $('#loginFrm').serialize();
// alert(credentials);

var url = "/login?" + credentials;

$.getJSON(url, function (data)  {
    alert("Inside getJSON callback method");
    alert(data);
});
}

Also, here is the code from LoginServlet. The Servlet is mapped to URL pattern- /login

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    logger.info("Inside LoginServlet");

    response.setContentType("application/json");

    String email = request.getParameter("email") == null ? "" : request.getParameter("email");
    String password = request.getParameter("password") == null ? "" : request.getParameter("password");

    logger.info("email:: " + email + " password::" + password);

    Customer customer = null;
    Developer developer = null;

    JsonObjectBuilder objBuilder = Json.createObjectBuilder();
    JsonObject responseObject = null;

    PrintWriter pout = response.getWriter();

    if (!email.equals("") && !password.equals("")) {
        boolean loginSuccess = false;
        logger.info("Trying to load customer entity");
        customer = ofy().load().key(Key.create(Customer.class, email)).now();

        if (null == customer) {
            logger.info("customer entity not found. Trying to load developer entity");
            developer = ofy().load().key(Key.create(Developer.class, email)).now();

            if (developer != null) {
                logger.info("developer entity found");
                if (developer.getPassword().equals(password)) {
                    logger.info("Developer login successful");
                    loginSuccess = true;

                    responseObject = objBuilder.add("status", "success").add("userType", "developer").add("forwardUrl", "Home.jsp").build();

                    logger.info("JsonObject constructed as:: " + responseObject);
                    pout.println(responseObject.toString());
                    pout.flush();

                    // request.getRequestDispatcher("Home.jsp").forward(request, response);
                }
            }
        } else {
            if (customer.getPassword().equals(password)) {
                logger.info("Customer login successful");
                loginSuccess = true;

                responseObject = objBuilder.add("status", "success").add("userType", "customer").add("forwardUrl", "Home.jsp").build();

                logger.info("JsonObject constructed as:: " + responseObject);
                pout.println(responseObject.toString());
                pout.flush();

                // request.getRequestDispatcher("Home.jsp").forward(request, response);
            }
        }

        if (!loginSuccess) {
            // Login Failure
            responseObject = objBuilder.add("status", "faliure").build();
            logger.info("Login Faliure. JsonObject constructed as:: " + responseObject);

            pout.println(responseObject.toString());
            pout.flush();
        }

    }
}

My problem is that the Servlet does not seem to be returning the response to getJSON(). The network tab from Firefox does not show any response from the request. It does not even prints the HTTP status code of the request.

However, I do know that the request is reaching the LoginServlet, as is evident from the following logs-

[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doGet
[INFO] INFO: Request inside doGet method. Calling doPost with it
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: Inside LoginServlet
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: email:: [email protected] password::prateek
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: Trying to load customer entity
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: customer entity not found. Trying to load developer entity
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: developer entity found
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: Developer login successful
[INFO] Jul 20, 2015 10:42:13 PM com.allissues.logic.LoginServlet doPost
[INFO] INFO: JsonObject constructed as:: {"status":"success","userType":"developer","forwardUrl":"Home.jsp"}

But the response from the AJAX request is empty, and I am having troubles understanding where my code went wrong.

Can anybody please help me with this? Thanks in advance.

EDIT Also, when I access this URL from the web page- http://localhost:8080/[email protected]&password=prateek

It gives me the proper JSONObject I am expecting- {"status":"success","userType":"developer","forwardUrl":"Home.jsp"}

1
Any console errors? Do you see the request in the Network tab of your debugging tool? - Dave

1 Answers

2
votes

Many problems here.

  1. It's a very bad idea to use GET to pass login credentials. URLs are typically cached in the browser, server logs, and other easy-to-read areas in plain text. Use POST to pass the credentials, ensure they're passed via SSL

  2. Never log credentials (you may only be doing this for debugging, which is natural, but it's a very bad practice to get into)

  3. Your servlet is wired to respond with doPost(), but you're using an AJAX GET to pass the data. Based on your logs, it looks like you might be delegating to doPost from within doGet, but that's still not a great practice--just use a POST from the get-go.

  4. You're using a button element to trigger your login action, but not specifying a type attribute or suppressing the default click behavior. By default, the button element acts as a submit button, which means a user clicking the button will first trigger the AJAX behavior, then trigger the native form submission behavior (that is, submit the data contained in #loginFrm to the currently loaded URL via POST). Since that by default reloads the page, the AJAX callback will not fire as expected.

To fix, do 2 things:

1) Clean up your security

A. Use POST instead of GET. jQuery will take care of parsing the JSON for you:

$.post("/login", credentials, function (data)  {
    alert("Inside getJSON callback method");
    alert(data);
});

B. Remove sensitive data from logs. Also remember to remove your server-side logging statements that dump sensitive user data to the log.

C. Do not respond to GET requests from your Login servlet. Your doGet() servlet method should return a 404, not log any sensitive data, and not attempt take any actions on that data.

2) Suppress the default actions

You want jQuery's preventDefault() method in your method body. Don't forget to also add a form submission handler to prevent default form submission behavior and delegate to your loginAction method:

$('#btnLogin').on('click', loginAction);
$('#loginFrm').on('submit', loginAction);

function loginAction(eventObject)  {
    eventObject.preventDefault();
    var userEmail = $('#email').val();
    ...