In this example, we will learn how to implement programmatic security by using HttpServletRequest.login() and HttpServletRequest.logout() methods.
For implementing programmatic security, we don't have to use @ServletSecurity which is a declarative approach to specify security constraints on a servlet. Also we will not specify auth-method in web.xml with value 'BASIC'. By using login() and logout() methods, we can implement a form based login which is an alternative approach to Basic Authentication.
Example
The Servlets
@WebServlet(name = "securedServlet", urlPatterns = {"/app"})
public class MySecuredServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
Principal principal = req.getUserPrincipal();
if (principal == null || !req.isUserInRole("employee")) {
LoginHandlerServlet.forwardToLogin(req, resp, null);
return;
}
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.println("Welcome to the secured app!");
writer.printf("<br/>User: " + req.getRemoteUser());
writer.printf("<br/>time: " + LocalDateTime.now());
writer.println("<br/><a href='/logout'>Logout</a>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
@WebServlet(name = "loginServlet", urlPatterns = {"/loginHandler"})
public class LoginHandlerServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String theUser = req.getParameter("theUser");
String thePassword = req.getParameter("thePassword");
try {
req.login(theUser, thePassword);
} catch (ServletException e) {
System.out.println(e.getMessage());
forwardToLogin(req, resp, "Error: " + e.getMessage());
return;
}
boolean loggedIn = req.getUserPrincipal() != null && req.isUserInRole("employee");
if (loggedIn) {
resp.sendRedirect("/app");
} else {
forwardToLogin(req, resp, "Login failed.");
}
}
public static void forwardToLogin(HttpServletRequest req, HttpServletResponse resp,
String errorMessage)
throws ServletException, IOException {
req.setAttribute("errorMsg", errorMessage);
req.getRequestDispatcher("/login.jsp")
.forward(req, resp);
}
}
@WebServlet(name = "logoutServlet", urlPatterns = {"/logout"})
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.logout();
Principal principal = req.getUserPrincipal();
if (principal != null) {
throw new RuntimeException("Cannot log out the user");
}
resp.sendRedirect("/app");
}
}
JSP Page
We have to provide a custom login form for this example, which is different from the Basic Authentication case where most of the browser provide an automatic login form (as we saw in the last two examples).
src/main/webapp/login.jsp<html>
<body>
<div style="color:red">
<%
Object msg = request.getAttribute("errorMsg");
if(msg != null ){
out.println(msg);
}
%>
</div>
<form action="/loginHandler" method="post">
<table>
<tr>
<td> User:</td>
<td><input type="text" name="theUser"/></td>
</tr>
<tr>
<td> Password:</td>
<td><input type="password" name="thePassword"/></td>
</tr>
</table>
<input type="submit" value="Submit"/>
</form>
</body>
</html>
Adding tomcat-users.xml
As we are going to run embedded tomcat for this example, we will add tomcat-user.xml (as a realm) in the project.
src/main/webapp/config/tomcat-users.xml<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
<role rolename="employee"/>
<user username="Joe" password="123" roles="employee"/>
</tomcat-users>
Specifying tomcat-user.xml location
pom.xml
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<tomcatUsers>src/main/webapp/config/tomcat-users.xml</tomcatUsers>
</configuration>
</plugin>
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run-war
Output
On submitting user/password:
On clicking logout link:
On entering wrong username/password:
Example ProjectDependencies and Technologies Used: - javax.servlet-api 3.1.0 Java Servlet API
- JDK 1.8
- Maven 3.3.9
|