Java Servlet & JSP simple loginTomcat/JSP/servlets web-projectfile downloading using jsp but not readableA Java Web App with Servlets, JSP and Session: shopping cart exampleServlet and JSP for user registration, with CAPTCHA and error handlingOpen source Pastebin tool made in JSP and servletAuthorization token from servlet filter stores user nameJava login system using JSP and servletsThread Safe ServletSimple login with jspAsking data to a Servlet from jsp and send them back to the jsp
Averting Real Women Don’t Wear Dresses
Why isn’t the tax system continuous rather than bracketed?
Why does the A-4 Skyhawk sit nose-up when on ground?
Is this one of the engines from the 9/11 aircraft?
Why is C++ initial allocation so much larger than C's?
Should I include salary information on my CV?
Alphabet completion rate
Should I tell my insurance company I'm making payments on my new car?
Do French speakers not use the subjunctive informally?
Rvalues, lvalues and formal definitions
STM Microcontroller burns every time
How to perform Login Authentication at the client-side?
What is the line crossing the Pacific Ocean that is shown on maps?
Layout of complex table
What do you call the action of someone tackling a stronger person?
Should my manager be aware of private LinkedIn approaches I receive? How to politely have this happen?
MH370 blackbox - is it still possible to retrieve data from it?
Intuitively, why does putting capacitors in series decrease the equivalent capacitance?
How can I convince my reader that I will not use a certain trope?
How to determine what is the correct level of detail when modelling?
Are neural networks the wrong tool to solve this 2D platformer/shooter game? Is there a proven way to frame this problem to a neural network?
Ending: accusative or not?
Why would people reject a god's purely beneficial blessing?
How can I repair scratches on a painted French door?
Java Servlet & JSP simple login
Tomcat/JSP/servlets web-projectfile downloading using jsp but not readableA Java Web App with Servlets, JSP and Session: shopping cart exampleServlet and JSP for user registration, with CAPTCHA and error handlingOpen source Pastebin tool made in JSP and servletAuthorization token from servlet filter stores user nameJava login system using JSP and servletsThread Safe ServletSimple login with jspAsking data to a Servlet from jsp and send them back to the jsp
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I am currently learning Java Servlets and JSP at university. As a little practice I created a project where I want to be able to login into a protected area. Now, I got it working by using a RequestDispatcher. However, after I have been forwarded to the protected area, the URL in the browser shows http://localhost:8080/jspractice02/FrontController
. I think it would make more sense to be http://localhost:8080/jspractice02/protected/dashboard.jsp
. Should I use sendRedirect
instead of a Dispatcher?
Another thing is that I don't know if my code structure is somewhat senseful, especially how I handle the login. I would love to get some feedback on that.
Directory Structure
+-- src
| +-- main
| +-- java
| | +-- de.practice.PresentationLayer
| | +-- FrontController.java
| +-- webapp
| | +-- home.jsp
| | +-- protected
| | +-- dashboard.jsp
| | +-- add-student.jsp
FrontController.java
package de.practice.Presentation;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class FrontController
*/
@WebServlet("/FrontController")
public class FrontController extends HttpServlet
private static final long serialVersionUID = 1L;
private static String username = "";
private static String password = "";
private static String queryString = "";
/**
* Constructor
*/
public FrontController()
super();
/**
* doGet
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
/**
* doPost
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
doGet(request, response);
login(request, response);
/**
* validPassword
* @param request
* @param response
* @param password
* @return
*/
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
/**
* validUsername
* @param request
* @param response
* @param username
* @return
*/
private boolean validUsername(HttpServletRequest request, HttpServletResponse response, String username)
if(username.length() >= 3)
return true;
return false;
/**
*
* @param request
* @param response
* @param password
* @param username
* @throws IOException
* @throws ServletException
*/
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
// Get username and password
username = request.getParameter("username");
password = request.getParameter("password");
// check if they are valid
if(validUsername(request, response, username) && validPassword(request, response, password))
// If valid create session
HttpSession session = request.getSession();
session.setAttribute("username", username);
// and redirect to protected area
RequestDispatcher rd = request.getRequestDispatcher("protected/dashboard.jsp");
rd.forward(request, response);
else
// Code for invalid login
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
<%@ include file="partials/header.jsp"%>
<section id="start" class="panel">
<div class="container">
<h1>Home</h1>
<form class="form" method="post" action="FrontController">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control">
</div>
<input type="submit" name="submitBtn" class="btn btn-primary">
</form>
</div>
</section>
<%@ include file="partials/footer.jsp"%>
java authentication servlets jsp
$endgroup$
add a comment |
$begingroup$
I am currently learning Java Servlets and JSP at university. As a little practice I created a project where I want to be able to login into a protected area. Now, I got it working by using a RequestDispatcher. However, after I have been forwarded to the protected area, the URL in the browser shows http://localhost:8080/jspractice02/FrontController
. I think it would make more sense to be http://localhost:8080/jspractice02/protected/dashboard.jsp
. Should I use sendRedirect
instead of a Dispatcher?
Another thing is that I don't know if my code structure is somewhat senseful, especially how I handle the login. I would love to get some feedback on that.
Directory Structure
+-- src
| +-- main
| +-- java
| | +-- de.practice.PresentationLayer
| | +-- FrontController.java
| +-- webapp
| | +-- home.jsp
| | +-- protected
| | +-- dashboard.jsp
| | +-- add-student.jsp
FrontController.java
package de.practice.Presentation;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class FrontController
*/
@WebServlet("/FrontController")
public class FrontController extends HttpServlet
private static final long serialVersionUID = 1L;
private static String username = "";
private static String password = "";
private static String queryString = "";
/**
* Constructor
*/
public FrontController()
super();
/**
* doGet
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
/**
* doPost
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
doGet(request, response);
login(request, response);
/**
* validPassword
* @param request
* @param response
* @param password
* @return
*/
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
/**
* validUsername
* @param request
* @param response
* @param username
* @return
*/
private boolean validUsername(HttpServletRequest request, HttpServletResponse response, String username)
if(username.length() >= 3)
return true;
return false;
/**
*
* @param request
* @param response
* @param password
* @param username
* @throws IOException
* @throws ServletException
*/
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
// Get username and password
username = request.getParameter("username");
password = request.getParameter("password");
// check if they are valid
if(validUsername(request, response, username) && validPassword(request, response, password))
// If valid create session
HttpSession session = request.getSession();
session.setAttribute("username", username);
// and redirect to protected area
RequestDispatcher rd = request.getRequestDispatcher("protected/dashboard.jsp");
rd.forward(request, response);
else
// Code for invalid login
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
<%@ include file="partials/header.jsp"%>
<section id="start" class="panel">
<div class="container">
<h1>Home</h1>
<form class="form" method="post" action="FrontController">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control">
</div>
<input type="submit" name="submitBtn" class="btn btn-primary">
</form>
</div>
</section>
<%@ include file="partials/footer.jsp"%>
java authentication servlets jsp
$endgroup$
add a comment |
$begingroup$
I am currently learning Java Servlets and JSP at university. As a little practice I created a project where I want to be able to login into a protected area. Now, I got it working by using a RequestDispatcher. However, after I have been forwarded to the protected area, the URL in the browser shows http://localhost:8080/jspractice02/FrontController
. I think it would make more sense to be http://localhost:8080/jspractice02/protected/dashboard.jsp
. Should I use sendRedirect
instead of a Dispatcher?
Another thing is that I don't know if my code structure is somewhat senseful, especially how I handle the login. I would love to get some feedback on that.
Directory Structure
+-- src
| +-- main
| +-- java
| | +-- de.practice.PresentationLayer
| | +-- FrontController.java
| +-- webapp
| | +-- home.jsp
| | +-- protected
| | +-- dashboard.jsp
| | +-- add-student.jsp
FrontController.java
package de.practice.Presentation;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class FrontController
*/
@WebServlet("/FrontController")
public class FrontController extends HttpServlet
private static final long serialVersionUID = 1L;
private static String username = "";
private static String password = "";
private static String queryString = "";
/**
* Constructor
*/
public FrontController()
super();
/**
* doGet
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
/**
* doPost
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
doGet(request, response);
login(request, response);
/**
* validPassword
* @param request
* @param response
* @param password
* @return
*/
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
/**
* validUsername
* @param request
* @param response
* @param username
* @return
*/
private boolean validUsername(HttpServletRequest request, HttpServletResponse response, String username)
if(username.length() >= 3)
return true;
return false;
/**
*
* @param request
* @param response
* @param password
* @param username
* @throws IOException
* @throws ServletException
*/
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
// Get username and password
username = request.getParameter("username");
password = request.getParameter("password");
// check if they are valid
if(validUsername(request, response, username) && validPassword(request, response, password))
// If valid create session
HttpSession session = request.getSession();
session.setAttribute("username", username);
// and redirect to protected area
RequestDispatcher rd = request.getRequestDispatcher("protected/dashboard.jsp");
rd.forward(request, response);
else
// Code for invalid login
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
<%@ include file="partials/header.jsp"%>
<section id="start" class="panel">
<div class="container">
<h1>Home</h1>
<form class="form" method="post" action="FrontController">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control">
</div>
<input type="submit" name="submitBtn" class="btn btn-primary">
</form>
</div>
</section>
<%@ include file="partials/footer.jsp"%>
java authentication servlets jsp
$endgroup$
I am currently learning Java Servlets and JSP at university. As a little practice I created a project where I want to be able to login into a protected area. Now, I got it working by using a RequestDispatcher. However, after I have been forwarded to the protected area, the URL in the browser shows http://localhost:8080/jspractice02/FrontController
. I think it would make more sense to be http://localhost:8080/jspractice02/protected/dashboard.jsp
. Should I use sendRedirect
instead of a Dispatcher?
Another thing is that I don't know if my code structure is somewhat senseful, especially how I handle the login. I would love to get some feedback on that.
Directory Structure
+-- src
| +-- main
| +-- java
| | +-- de.practice.PresentationLayer
| | +-- FrontController.java
| +-- webapp
| | +-- home.jsp
| | +-- protected
| | +-- dashboard.jsp
| | +-- add-student.jsp
FrontController.java
package de.practice.Presentation;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class FrontController
*/
@WebServlet("/FrontController")
public class FrontController extends HttpServlet
private static final long serialVersionUID = 1L;
private static String username = "";
private static String password = "";
private static String queryString = "";
/**
* Constructor
*/
public FrontController()
super();
/**
* doGet
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
/**
* doPost
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
doGet(request, response);
login(request, response);
/**
* validPassword
* @param request
* @param response
* @param password
* @return
*/
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
/**
* validUsername
* @param request
* @param response
* @param username
* @return
*/
private boolean validUsername(HttpServletRequest request, HttpServletResponse response, String username)
if(username.length() >= 3)
return true;
return false;
/**
*
* @param request
* @param response
* @param password
* @param username
* @throws IOException
* @throws ServletException
*/
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
// Get username and password
username = request.getParameter("username");
password = request.getParameter("password");
// check if they are valid
if(validUsername(request, response, username) && validPassword(request, response, password))
// If valid create session
HttpSession session = request.getSession();
session.setAttribute("username", username);
// and redirect to protected area
RequestDispatcher rd = request.getRequestDispatcher("protected/dashboard.jsp");
rd.forward(request, response);
else
// Code for invalid login
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
<%@ include file="partials/header.jsp"%>
<section id="start" class="panel">
<div class="container">
<h1>Home</h1>
<form class="form" method="post" action="FrontController">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control">
</div>
<input type="submit" name="submitBtn" class="btn btn-primary">
</form>
</div>
</section>
<%@ include file="partials/footer.jsp"%>
java authentication servlets jsp
java authentication servlets jsp
edited Jun 8 at 17:13
200_success
134k21 gold badges169 silver badges440 bronze badges
134k21 gold badges169 silver badges440 bronze badges
asked Jun 8 at 13:22
Dennis FinkDennis Fink
1738 bronze badges
1738 bronze badges
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
Critical error
private static String username = "";
private static String password = "";
private static String queryString = "";
You should never keep request-scoped data in a field in a servlet. Servlet is created only once during application startup, and shared among all requests. So if several clients connect to your servlet at the same time, they might not reach the protected page, even if they provide correct password. It will also lead to setting wrong username attribute in the session object. If you had customized pages for each user, this could also lead to people seeing protected pages of other people.
Solution - extract the sensitive request-scoped data in doGet method only. Also, simply removing the static
keyword will not resolve the issue.
Code style
- Get rid of empty JavaDoc that only makes the code harder to read
- Get rid of obvious comments that only make the code harder to read, like
// Get username and password
- Do not introduce redunant code (constructor that only calls
super()
) - Improve method ordering. When you call
validUsername()
inlogin()
, thenvalidUsername()
should be belowlogin()
in the class. this improves readability. - Get rid of redundant logic. For example, the
validUsername()
method body can be elegantly expressed in one line -return username.length() >= 3
. By the way, I think this method should be namedisUsernameValid()
in my opinion. - Do not pass unnecessary arguments to methods. For example,
validUsername()
does not needrequest
andresponse
.
Other
The browser shows http://localhost:8080/jspractice02/FrontController
because you've annotated the class with @WebServlet("/FrontController")
. Please read the documentation on how that works.
I'm not sure if calling doGet()
from doPost()
is necessary (and I'm not sure if it's best practice). Your doPost()
should just login the user and redirect them if the credentials provided are valid.
$endgroup$
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
add a comment |
$begingroup$
package de.practice.Presentation
That's not a valid package name under the Java convention. Packages are all lowercase with maybe underscores.
private static String username = "";
You don't want these static
, actually, you don't want them as fields at all. When dealing with requests, you have to consider that one instance of the same class might handle multiple requests simultaneously. Having a state in the class (f.e. fields) has to be carefully considered.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
Consider mapping your requests and actions in a way which allows you to refer to locations directly without having to resort to a big switch statement.
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
We all know that's just a placeholder, but you could return directly:
return password.length() >= 3;
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
You're repeating this action multiple times, consider a helper function. But you could also write that in one line.
/**
* Constructor
*/
You might as well omit the Javadoc if it's not going to be useful.
$endgroup$
add a comment |
$begingroup$
You've received some good comments on the detailed coding, so I'll focus on the design.
- Follow the single responsibility principle in your controller, it should do one thing, dispatch the commands it receives.
- The SRP will make it unnecessary to change the controller to add new commands. Replace your switch with a command mapping, see the Command Pattern. A good approach to this is to load the commands from a property file into a Hashmap; so
Command=ClassName
that maps the command-name to a class name. - Use the
Class.forName(className).newInstance()
idiom to construct new instances of the commands on demand. - Create a hierarchy of the access controlled commands to minimise the risk of a security/access holes. So all the controlled commands must inherit from an access controlled command.
See this answer for a more elaborate explanation : https://softwareengineering.stackexchange.com/a/345714/241947
$endgroup$
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
$begingroup$
Oh,className
is not a placeholder but an actual variable, then I get what you mean.
$endgroup$
– Bobby
Jun 13 at 19:11
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f221929%2fjava-servlet-jsp-simple-login%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Critical error
private static String username = "";
private static String password = "";
private static String queryString = "";
You should never keep request-scoped data in a field in a servlet. Servlet is created only once during application startup, and shared among all requests. So if several clients connect to your servlet at the same time, they might not reach the protected page, even if they provide correct password. It will also lead to setting wrong username attribute in the session object. If you had customized pages for each user, this could also lead to people seeing protected pages of other people.
Solution - extract the sensitive request-scoped data in doGet method only. Also, simply removing the static
keyword will not resolve the issue.
Code style
- Get rid of empty JavaDoc that only makes the code harder to read
- Get rid of obvious comments that only make the code harder to read, like
// Get username and password
- Do not introduce redunant code (constructor that only calls
super()
) - Improve method ordering. When you call
validUsername()
inlogin()
, thenvalidUsername()
should be belowlogin()
in the class. this improves readability. - Get rid of redundant logic. For example, the
validUsername()
method body can be elegantly expressed in one line -return username.length() >= 3
. By the way, I think this method should be namedisUsernameValid()
in my opinion. - Do not pass unnecessary arguments to methods. For example,
validUsername()
does not needrequest
andresponse
.
Other
The browser shows http://localhost:8080/jspractice02/FrontController
because you've annotated the class with @WebServlet("/FrontController")
. Please read the documentation on how that works.
I'm not sure if calling doGet()
from doPost()
is necessary (and I'm not sure if it's best practice). Your doPost()
should just login the user and redirect them if the credentials provided are valid.
$endgroup$
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
add a comment |
$begingroup$
Critical error
private static String username = "";
private static String password = "";
private static String queryString = "";
You should never keep request-scoped data in a field in a servlet. Servlet is created only once during application startup, and shared among all requests. So if several clients connect to your servlet at the same time, they might not reach the protected page, even if they provide correct password. It will also lead to setting wrong username attribute in the session object. If you had customized pages for each user, this could also lead to people seeing protected pages of other people.
Solution - extract the sensitive request-scoped data in doGet method only. Also, simply removing the static
keyword will not resolve the issue.
Code style
- Get rid of empty JavaDoc that only makes the code harder to read
- Get rid of obvious comments that only make the code harder to read, like
// Get username and password
- Do not introduce redunant code (constructor that only calls
super()
) - Improve method ordering. When you call
validUsername()
inlogin()
, thenvalidUsername()
should be belowlogin()
in the class. this improves readability. - Get rid of redundant logic. For example, the
validUsername()
method body can be elegantly expressed in one line -return username.length() >= 3
. By the way, I think this method should be namedisUsernameValid()
in my opinion. - Do not pass unnecessary arguments to methods. For example,
validUsername()
does not needrequest
andresponse
.
Other
The browser shows http://localhost:8080/jspractice02/FrontController
because you've annotated the class with @WebServlet("/FrontController")
. Please read the documentation on how that works.
I'm not sure if calling doGet()
from doPost()
is necessary (and I'm not sure if it's best practice). Your doPost()
should just login the user and redirect them if the credentials provided are valid.
$endgroup$
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
add a comment |
$begingroup$
Critical error
private static String username = "";
private static String password = "";
private static String queryString = "";
You should never keep request-scoped data in a field in a servlet. Servlet is created only once during application startup, and shared among all requests. So if several clients connect to your servlet at the same time, they might not reach the protected page, even if they provide correct password. It will also lead to setting wrong username attribute in the session object. If you had customized pages for each user, this could also lead to people seeing protected pages of other people.
Solution - extract the sensitive request-scoped data in doGet method only. Also, simply removing the static
keyword will not resolve the issue.
Code style
- Get rid of empty JavaDoc that only makes the code harder to read
- Get rid of obvious comments that only make the code harder to read, like
// Get username and password
- Do not introduce redunant code (constructor that only calls
super()
) - Improve method ordering. When you call
validUsername()
inlogin()
, thenvalidUsername()
should be belowlogin()
in the class. this improves readability. - Get rid of redundant logic. For example, the
validUsername()
method body can be elegantly expressed in one line -return username.length() >= 3
. By the way, I think this method should be namedisUsernameValid()
in my opinion. - Do not pass unnecessary arguments to methods. For example,
validUsername()
does not needrequest
andresponse
.
Other
The browser shows http://localhost:8080/jspractice02/FrontController
because you've annotated the class with @WebServlet("/FrontController")
. Please read the documentation on how that works.
I'm not sure if calling doGet()
from doPost()
is necessary (and I'm not sure if it's best practice). Your doPost()
should just login the user and redirect them if the credentials provided are valid.
$endgroup$
Critical error
private static String username = "";
private static String password = "";
private static String queryString = "";
You should never keep request-scoped data in a field in a servlet. Servlet is created only once during application startup, and shared among all requests. So if several clients connect to your servlet at the same time, they might not reach the protected page, even if they provide correct password. It will also lead to setting wrong username attribute in the session object. If you had customized pages for each user, this could also lead to people seeing protected pages of other people.
Solution - extract the sensitive request-scoped data in doGet method only. Also, simply removing the static
keyword will not resolve the issue.
Code style
- Get rid of empty JavaDoc that only makes the code harder to read
- Get rid of obvious comments that only make the code harder to read, like
// Get username and password
- Do not introduce redunant code (constructor that only calls
super()
) - Improve method ordering. When you call
validUsername()
inlogin()
, thenvalidUsername()
should be belowlogin()
in the class. this improves readability. - Get rid of redundant logic. For example, the
validUsername()
method body can be elegantly expressed in one line -return username.length() >= 3
. By the way, I think this method should be namedisUsernameValid()
in my opinion. - Do not pass unnecessary arguments to methods. For example,
validUsername()
does not needrequest
andresponse
.
Other
The browser shows http://localhost:8080/jspractice02/FrontController
because you've annotated the class with @WebServlet("/FrontController")
. Please read the documentation on how that works.
I'm not sure if calling doGet()
from doPost()
is necessary (and I'm not sure if it's best practice). Your doPost()
should just login the user and redirect them if the credentials provided are valid.
edited Jun 9 at 10:30
answered Jun 8 at 16:41
RK1RK1
3792 silver badges14 bronze badges
3792 silver badges14 bronze badges
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
add a comment |
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Do not introduce redunant code (constructor that only calls super())" Keep in mind that there are instances when declaring default constructors is required, for example when the binary is being obfuscated (obfuscator strips the default ones, but leaves user defined ones intact).
$endgroup$
– Bobby
Jun 9 at 8:32
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
$begingroup$
"Can you think how?" We're doing a code review here, not playing guessing games. Just tell the people.
$endgroup$
– Bobby
Jun 9 at 8:33
add a comment |
$begingroup$
package de.practice.Presentation
That's not a valid package name under the Java convention. Packages are all lowercase with maybe underscores.
private static String username = "";
You don't want these static
, actually, you don't want them as fields at all. When dealing with requests, you have to consider that one instance of the same class might handle multiple requests simultaneously. Having a state in the class (f.e. fields) has to be carefully considered.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
Consider mapping your requests and actions in a way which allows you to refer to locations directly without having to resort to a big switch statement.
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
We all know that's just a placeholder, but you could return directly:
return password.length() >= 3;
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
You're repeating this action multiple times, consider a helper function. But you could also write that in one line.
/**
* Constructor
*/
You might as well omit the Javadoc if it's not going to be useful.
$endgroup$
add a comment |
$begingroup$
package de.practice.Presentation
That's not a valid package name under the Java convention. Packages are all lowercase with maybe underscores.
private static String username = "";
You don't want these static
, actually, you don't want them as fields at all. When dealing with requests, you have to consider that one instance of the same class might handle multiple requests simultaneously. Having a state in the class (f.e. fields) has to be carefully considered.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
Consider mapping your requests and actions in a way which allows you to refer to locations directly without having to resort to a big switch statement.
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
We all know that's just a placeholder, but you could return directly:
return password.length() >= 3;
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
You're repeating this action multiple times, consider a helper function. But you could also write that in one line.
/**
* Constructor
*/
You might as well omit the Javadoc if it's not going to be useful.
$endgroup$
add a comment |
$begingroup$
package de.practice.Presentation
That's not a valid package name under the Java convention. Packages are all lowercase with maybe underscores.
private static String username = "";
You don't want these static
, actually, you don't want them as fields at all. When dealing with requests, you have to consider that one instance of the same class might handle multiple requests simultaneously. Having a state in the class (f.e. fields) has to be carefully considered.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
Consider mapping your requests and actions in a way which allows you to refer to locations directly without having to resort to a big switch statement.
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
We all know that's just a placeholder, but you could return directly:
return password.length() >= 3;
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
You're repeating this action multiple times, consider a helper function. But you could also write that in one line.
/**
* Constructor
*/
You might as well omit the Javadoc if it's not going to be useful.
$endgroup$
package de.practice.Presentation
That's not a valid package name under the Java convention. Packages are all lowercase with maybe underscores.
private static String username = "";
You don't want these static
, actually, you don't want them as fields at all. When dealing with requests, you have to consider that one instance of the same class might handle multiple requests simultaneously. Having a state in the class (f.e. fields) has to be carefully considered.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
String jsp = "";
queryString = request.getParameter("action");
if(queryString != null)
switch(queryString)
case "addStudent":
jsp = "protected/student.jsp";
RequestDispatcher rd = request.getRequestDispatcher(jsp);
rd.forward(request, response);
Consider mapping your requests and actions in a way which allows you to refer to locations directly without having to resort to a big switch statement.
private boolean validPassword(HttpServletRequest request, HttpServletResponse response, String password)
if(password.length() >= 3)
return true;
return false;
We all know that's just a placeholder, but you could return directly:
return password.length() >= 3;
RequestDispatcher rd = request.getRequestDispatcher("login-failed.jsp");
rd.forward(request, response);
You're repeating this action multiple times, consider a helper function. But you could also write that in one line.
/**
* Constructor
*/
You might as well omit the Javadoc if it's not going to be useful.
answered Jun 8 at 16:35
BobbyBobby
5,1881 gold badge23 silver badges41 bronze badges
5,1881 gold badge23 silver badges41 bronze badges
add a comment |
add a comment |
$begingroup$
You've received some good comments on the detailed coding, so I'll focus on the design.
- Follow the single responsibility principle in your controller, it should do one thing, dispatch the commands it receives.
- The SRP will make it unnecessary to change the controller to add new commands. Replace your switch with a command mapping, see the Command Pattern. A good approach to this is to load the commands from a property file into a Hashmap; so
Command=ClassName
that maps the command-name to a class name. - Use the
Class.forName(className).newInstance()
idiom to construct new instances of the commands on demand. - Create a hierarchy of the access controlled commands to minimise the risk of a security/access holes. So all the controlled commands must inherit from an access controlled command.
See this answer for a more elaborate explanation : https://softwareengineering.stackexchange.com/a/345714/241947
$endgroup$
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
$begingroup$
Oh,className
is not a placeholder but an actual variable, then I get what you mean.
$endgroup$
– Bobby
Jun 13 at 19:11
add a comment |
$begingroup$
You've received some good comments on the detailed coding, so I'll focus on the design.
- Follow the single responsibility principle in your controller, it should do one thing, dispatch the commands it receives.
- The SRP will make it unnecessary to change the controller to add new commands. Replace your switch with a command mapping, see the Command Pattern. A good approach to this is to load the commands from a property file into a Hashmap; so
Command=ClassName
that maps the command-name to a class name. - Use the
Class.forName(className).newInstance()
idiom to construct new instances of the commands on demand. - Create a hierarchy of the access controlled commands to minimise the risk of a security/access holes. So all the controlled commands must inherit from an access controlled command.
See this answer for a more elaborate explanation : https://softwareengineering.stackexchange.com/a/345714/241947
$endgroup$
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
$begingroup$
Oh,className
is not a placeholder but an actual variable, then I get what you mean.
$endgroup$
– Bobby
Jun 13 at 19:11
add a comment |
$begingroup$
You've received some good comments on the detailed coding, so I'll focus on the design.
- Follow the single responsibility principle in your controller, it should do one thing, dispatch the commands it receives.
- The SRP will make it unnecessary to change the controller to add new commands. Replace your switch with a command mapping, see the Command Pattern. A good approach to this is to load the commands from a property file into a Hashmap; so
Command=ClassName
that maps the command-name to a class name. - Use the
Class.forName(className).newInstance()
idiom to construct new instances of the commands on demand. - Create a hierarchy of the access controlled commands to minimise the risk of a security/access holes. So all the controlled commands must inherit from an access controlled command.
See this answer for a more elaborate explanation : https://softwareengineering.stackexchange.com/a/345714/241947
$endgroup$
You've received some good comments on the detailed coding, so I'll focus on the design.
- Follow the single responsibility principle in your controller, it should do one thing, dispatch the commands it receives.
- The SRP will make it unnecessary to change the controller to add new commands. Replace your switch with a command mapping, see the Command Pattern. A good approach to this is to load the commands from a property file into a Hashmap; so
Command=ClassName
that maps the command-name to a class name. - Use the
Class.forName(className).newInstance()
idiom to construct new instances of the commands on demand. - Create a hierarchy of the access controlled commands to minimise the risk of a security/access holes. So all the controlled commands must inherit from an access controlled command.
See this answer for a more elaborate explanation : https://softwareengineering.stackexchange.com/a/345714/241947
edited Jun 13 at 17:19
answered Jun 10 at 9:31
Martin SpamerMartin Spamer
3852 silver badges12 bronze badges
3852 silver badges12 bronze badges
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
$begingroup$
Oh,className
is not a placeholder but an actual variable, then I get what you mean.
$endgroup$
– Bobby
Jun 13 at 19:11
add a comment |
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
$begingroup$
Oh,className
is not a placeholder but an actual variable, then I get what you mean.
$endgroup$
– Bobby
Jun 13 at 19:11
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
"Use the Class.forName(className).newInstance() idiom to make the commands" Could you iterate on that?
$endgroup$
– Bobby
Jun 10 at 17:52
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
$begingroup$
@Bobby It is factory method that constructs a new instance of a class using a variable name rather than a hard coded class name. The className value needs to be fully qualified with the package but is really simple to use and extremely powerful factory method. I've added a link to the JavaDoc.
$endgroup$
– Martin Spamer
Jun 13 at 17:35
1
1
$begingroup$
Oh,
className
is not a placeholder but an actual variable, then I get what you mean.$endgroup$
– Bobby
Jun 13 at 19:11
$begingroup$
Oh,
className
is not a placeholder but an actual variable, then I get what you mean.$endgroup$
– Bobby
Jun 13 at 19:11
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f221929%2fjava-servlet-jsp-simple-login%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown