BAEL-2080 - Check if a user is logged-in with Servlets and JSP
* new module: javax-servlets-2
This commit is contained in:
parent
fc4c77ed94
commit
895044bfa3
|
@ -0,0 +1,5 @@
|
|||
## Servlets
|
||||
|
||||
This module contains articles about Servlets.
|
||||
|
||||
### Relevant Articles:
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.javax-servlets</groupId>
|
||||
<artifactId>javax-servlets-2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>javax-servlets-2</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- File Uploading -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons-fileupload.version}</version>
|
||||
</dependency>
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||
<version>${javax.servlet.jsp-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${org.apache.httpcomponents.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<org.apache.httpcomponents.version>4.5.13</org.apache.httpcomponents.version>
|
||||
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,80 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @since 6 de fev de 2022
|
||||
* @author ulisses
|
||||
*/
|
||||
public class User implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final HashMap<String, User> DB = new HashMap<>();
|
||||
static {
|
||||
DB.put("admin", new User("admin", "password"));
|
||||
DB.put("user", new User("user", "pass"));
|
||||
}
|
||||
|
||||
private String name;
|
||||
private String password;
|
||||
|
||||
private List<Date> logins = new ArrayList<Date>();
|
||||
|
||||
public User(String name, String password) {
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Date> getLogins() {
|
||||
return logins;
|
||||
}
|
||||
|
||||
public void setLogins(List<Date> logins) {
|
||||
this.logins = logins;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
User other = (User) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebFilter("/user-check/*")
|
||||
public class UserCheckFilter implements Filter {
|
||||
public static void forward(HttpServletRequest request, HttpServletResponse response, String page) throws ServletException, IOException {
|
||||
request.getRequestDispatcher("/WEB-INF/user.check" + page)
|
||||
.forward(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
if (!(req instanceof HttpServletRequest)) {
|
||||
throw new ServletException("Can only process HttpServletRequest");
|
||||
}
|
||||
|
||||
if (!(res instanceof HttpServletResponse)) {
|
||||
throw new ServletException("Can only process HttpServletResponse");
|
||||
}
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
request.setAttribute("origin", request.getRequestURI());
|
||||
|
||||
if (!request.getRequestURI()
|
||||
.contains("login") && request.getSession(false) == null) {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
forward(request, response, "/login.jsp");
|
||||
// we return here so the original servlet is not processed
|
||||
return;
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
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;
|
||||
|
||||
@WebServlet("/user-check/login")
|
||||
public class UserCheckLoginServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
if (request.getSession(false) != null) {
|
||||
response.sendRedirect(request.getContextPath() + "/user-check/home");
|
||||
return;
|
||||
}
|
||||
|
||||
String referer = (String) request.getAttribute("origin");
|
||||
request.setAttribute("origin", referer);
|
||||
UserCheckFilter.forward(request, response, "/login.jsp");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
String key = request.getParameter("name");
|
||||
String pass = request.getParameter("password");
|
||||
|
||||
User user = User.DB.get(key);
|
||||
if (user == null || !user.getPassword()
|
||||
.equals(pass)) {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
request.setAttribute("origin", request.getParameter("origin"));
|
||||
request.setAttribute("error", "invalid login");
|
||||
UserCheckFilter.forward(request, response, "/login.jsp");
|
||||
return;
|
||||
}
|
||||
|
||||
user.getLogins()
|
||||
.add(new Date());
|
||||
|
||||
HttpSession session = request.getSession();
|
||||
session.setAttribute("user", user);
|
||||
|
||||
String origin = request.getParameter("origin");
|
||||
if (origin == null || origin.contains("login"))
|
||||
origin = "./";
|
||||
|
||||
response.sendRedirect(origin);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
|
||||
@WebServlet("/user-check/logout")
|
||||
public class UserCheckLogoutServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
request.setAttribute("loggedOut", true);
|
||||
response.sendRedirect("./");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
|
||||
@WebServlet(name = "home", urlPatterns = { "/user-check/", "/user-check", "/user-check/home" })
|
||||
public class UserCheckServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null || session.getAttribute("user") == null) {
|
||||
throw new IllegalStateException("user not logged in");
|
||||
}
|
||||
|
||||
User user = (User) session.getAttribute("user");
|
||||
request.setAttribute("user", user);
|
||||
|
||||
UserCheckFilter.forward(request, response, "/home.jsp");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,31 @@
|
|||
<%@ page contentType="text/html;charset=UTF-8" session="false"%>
|
||||
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>login success - current session info</title>
|
||||
</head>
|
||||
<body>
|
||||
<section>
|
||||
<h2>user info</h2>
|
||||
<div>
|
||||
<span>name: ${user.name}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span>logins:</span>
|
||||
<ul>
|
||||
<c:forEach var="login" items="${user.logins}">
|
||||
<li>${login}</li>
|
||||
</c:forEach>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="${pageContext.request.contextPath}/user-check/logout">
|
||||
logout
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,33 @@
|
|||
<%@ page contentType="text/html;charset=UTF-8" session="false"%>
|
||||
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>login</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="${pageContext.request.contextPath}/user-check/login"
|
||||
method="POST">
|
||||
<input type="hidden" name="origin" value="${origin}">
|
||||
<c:if test="${not empty origin}">
|
||||
<div>* redirected to login from: ${origin}</div>
|
||||
</c:if>
|
||||
|
||||
<c:if test="${not empty error}">
|
||||
<div>* error: ${error}</div>
|
||||
</c:if>
|
||||
|
||||
<fieldset>
|
||||
<legend>credentials</legend>
|
||||
|
||||
<label for="name">name</label>
|
||||
<input type="text" name="name">
|
||||
|
||||
<label for="password">password</label>
|
||||
<input type="password" name="password">
|
||||
|
||||
<input type="submit">
|
||||
</fieldset>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,98 @@
|
|||
package com.baeldung.user.check;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.LaxRedirectStrategy;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UserCheckServletLiveTest {
|
||||
private static final String BASE_URL = "http://localhost:8080/javax-servlets-2/user-check";
|
||||
|
||||
@Mock
|
||||
HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
HttpServletResponse response;
|
||||
|
||||
private CloseableHttpClient buildClient() {
|
||||
return HttpClientBuilder.create()
|
||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCorrectCredentials_thenLoginSucceeds() throws Exception {
|
||||
try (CloseableHttpClient client = buildClient()) {
|
||||
HttpPost post = new HttpPost(BASE_URL + "/login");
|
||||
|
||||
List<BasicNameValuePair> form = new ArrayList<>();
|
||||
form.add(new BasicNameValuePair("name", "admin"));
|
||||
form.add(new BasicNameValuePair("password", "password"));
|
||||
|
||||
post.setEntity(new UrlEncodedFormEntity(form));
|
||||
try (CloseableHttpResponse response = client.execute(post)) {
|
||||
String body = EntityUtils.toString(response.getEntity());
|
||||
|
||||
assertTrue(response.getStatusLine()
|
||||
.getStatusCode() == 200);
|
||||
|
||||
assertTrue(body.contains("login success"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIncorrectCredentials_thenLoginFails() throws Exception {
|
||||
try (CloseableHttpClient client = buildClient()) {
|
||||
HttpPost post = new HttpPost(BASE_URL + "/login");
|
||||
|
||||
List<BasicNameValuePair> form = new ArrayList<>();
|
||||
form.add(new BasicNameValuePair("name", "admin"));
|
||||
form.add(new BasicNameValuePair("password", "invalid"));
|
||||
|
||||
post.setEntity(new UrlEncodedFormEntity(form));
|
||||
try (CloseableHttpResponse response = client.execute(post)) {
|
||||
String body = EntityUtils.toString(response.getEntity());
|
||||
|
||||
assertTrue(response.getStatusLine()
|
||||
.getStatusCode() == 401);
|
||||
|
||||
assertTrue(body.contains("invalid login"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNotLoggedIn_thenRedirectedToLoginPage() throws Exception {
|
||||
try (CloseableHttpClient client = buildClient()) {
|
||||
HttpGet get = new HttpGet(BASE_URL + "/home");
|
||||
|
||||
try (CloseableHttpResponse response = client.execute(get)) {
|
||||
String body = EntityUtils.toString(response.getEntity());
|
||||
|
||||
assertTrue(response.getStatusLine()
|
||||
.getStatusCode() == 401);
|
||||
|
||||
assertTrue(body.contains("redirected to login"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue