From b2903e087aa8e80df93d95e961d92bd2d924d182 Mon Sep 17 00:00:00 2001 From: Dell Date: Sun, 12 Apr 2026 00:22:50 +0300 Subject: [PATCH] feat/add login and logout logic with filters --- .../java/org/example/je/jdbc/dao/UserDao.java | 42 ++++++++++++++++++- .../java/org/example/je/jdbc/dto/UserDto.java | 12 +++++- .../je/jdbc/filter/AuthorizationFilter.java | 37 ++++++++++++++++ .../example/je/jdbc/filter/CharsetFilter.java | 18 ++++++++ .../example/je/jdbc/filter/LoggingFilter.java | 20 +++++++++ .../example/je/jdbc/filter/UnsaveFilter.java | 22 ++++++++++ .../example/je/jdbc/mapper/UserMapper.java | 28 +++++++++++++ .../example/je/jdbc/service/UserService.java | 8 ++++ .../example/je/jdbc/servlet/LoginServlet.java | 40 ++++++++++++++++++ .../je/jdbc/servlet/LogoutServlet.java | 18 ++++++++ src/main/java/utils/ConnectionManager.java | 1 + src/main/java/utils/UrlPath.java | 10 +++++ src/main/webapp/WEB-INF/jsp/header.jsp | 8 ++++ src/main/webapp/WEB-INF/jsp/login.jsp | 31 ++++++++++++++ src/main/webapp/WEB-INF/jsp/tickets.jsp | 1 + 15 files changed, 293 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/example/je/jdbc/filter/AuthorizationFilter.java create mode 100644 src/main/java/org/example/je/jdbc/filter/CharsetFilter.java create mode 100644 src/main/java/org/example/je/jdbc/filter/LoggingFilter.java create mode 100644 src/main/java/org/example/je/jdbc/filter/UnsaveFilter.java create mode 100644 src/main/java/org/example/je/jdbc/mapper/UserMapper.java create mode 100644 src/main/java/org/example/je/jdbc/servlet/LoginServlet.java create mode 100644 src/main/java/org/example/je/jdbc/servlet/LogoutServlet.java create mode 100644 src/main/java/utils/UrlPath.java create mode 100644 src/main/webapp/WEB-INF/jsp/header.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/login.jsp diff --git a/src/main/java/org/example/je/jdbc/dao/UserDao.java b/src/main/java/org/example/je/jdbc/dao/UserDao.java index 3bd75c2..b7a4d45 100644 --- a/src/main/java/org/example/je/jdbc/dao/UserDao.java +++ b/src/main/java/org/example/je/jdbc/dao/UserDao.java @@ -2,10 +2,11 @@ package org.example.je.jdbc.dao; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.example.je.jdbc.entity.User; +import org.example.je.jdbc.entity.*; import org.example.je.jdbc.exeption.DaoException; import utils.ConnectionManager; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; @@ -21,6 +22,12 @@ public class UserDao implements Dao { name, birthdate, email, password, role, gender) VALUES (?, ?, ?, ?, ?, ?); """; + + private final static String GET_BY_EMAIL_AND_PASSWORD_SQL = """ + SELECT * FROM public.users + WHERE email = ? and password = ?; + """; + @Override public User save(User user) { try (var connection = ConnectionManager.get(); @@ -64,6 +71,39 @@ public class UserDao implements Dao { return Optional.empty(); } + public Optional findByIdEmailAndPassword(String email, String password) { + try (var connection = ConnectionManager.get(); + var statement = connection.prepareStatement(GET_BY_EMAIL_AND_PASSWORD_SQL)) { + User user = null; + statement.setString(1, email); + statement.setString(2, password); + + var recordSet = statement.executeQuery(); + + if (recordSet.next()) { + user = buildUser(recordSet); + } + + return Optional.ofNullable(user); + + } catch (SQLException e) { + throw new DaoException(e); + } + } + + private User buildUser(ResultSet resultSet) throws SQLException { + return new User( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getString("email"), + resultSet.getString("password"), + Role.valueOf(resultSet.getString("role")), + Gender.valueOf(resultSet.getString("gender")), + resultSet.getDate("birthdate").toLocalDate() + ); + } + + public static UserDao getInstance() { return INSTANCE; } diff --git a/src/main/java/org/example/je/jdbc/dto/UserDto.java b/src/main/java/org/example/je/jdbc/dto/UserDto.java index a7cd382..f55f3a6 100644 --- a/src/main/java/org/example/je/jdbc/dto/UserDto.java +++ b/src/main/java/org/example/je/jdbc/dto/UserDto.java @@ -2,10 +2,18 @@ package org.example.je.jdbc.dto; import lombok.Builder; import lombok.Data; +import org.example.je.jdbc.entity.Gender; +import org.example.je.jdbc.entity.Role; + +import java.time.LocalDate; @Data @Builder public class UserDto { - private Long id; - private String email; + Long id; + String name; + String email; + LocalDate birthdate; + Role role; + Gender gender; } diff --git a/src/main/java/org/example/je/jdbc/filter/AuthorizationFilter.java b/src/main/java/org/example/je/jdbc/filter/AuthorizationFilter.java new file mode 100644 index 0000000..788479d --- /dev/null +++ b/src/main/java/org/example/je/jdbc/filter/AuthorizationFilter.java @@ -0,0 +1,37 @@ +package org.example.je.jdbc.filter; + +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Set; + +import static utils.UrlPath.LOGIN; +import static utils.UrlPath.REGISTRATION; + +@WebFilter("/*") +public class AuthorizationFilter implements Filter { + private static final Set PUBLIC_PATH = Set.of(LOGIN, REGISTRATION); + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + var uri = ((HttpServletRequest) servletRequest).getRequestURI(); + + if(isPublicPath(uri) || isUserLoggedIn(servletRequest)){ + filterChain.doFilter(servletRequest,servletResponse); + } else { + ((HttpServletResponse) servletResponse).sendRedirect("/login"); + } + } + + private boolean isUserLoggedIn(ServletRequest servletRequest) { + var user = ((HttpServletRequest) servletRequest).getSession().getAttribute("user"); + return user != null; + } + + private boolean isPublicPath(String uri) { + return PUBLIC_PATH.stream().anyMatch(uri::startsWith); + } +} diff --git a/src/main/java/org/example/je/jdbc/filter/CharsetFilter.java b/src/main/java/org/example/je/jdbc/filter/CharsetFilter.java new file mode 100644 index 0000000..06e4b42 --- /dev/null +++ b/src/main/java/org/example/je/jdbc/filter/CharsetFilter.java @@ -0,0 +1,18 @@ +package org.example.je.jdbc.filter; + +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +@WebFilter("/*") +public class CharsetFilter implements Filter { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); + servletRequest.setCharacterEncoding(StandardCharsets.UTF_8.name()); + + filterChain.doFilter(servletRequest,servletResponse); + } +} diff --git a/src/main/java/org/example/je/jdbc/filter/LoggingFilter.java b/src/main/java/org/example/je/jdbc/filter/LoggingFilter.java new file mode 100644 index 0000000..83ef800 --- /dev/null +++ b/src/main/java/org/example/je/jdbc/filter/LoggingFilter.java @@ -0,0 +1,20 @@ +package org.example.je.jdbc.filter; + +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; + +import java.io.IOException; +import java.util.Arrays; + +@WebFilter("/*") +public class LoggingFilter implements Filter { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + System.out.println(((HttpServletRequest) servletRequest).getSession().getAttribute("user")); + servletRequest.getParameterMap().forEach((k, v) -> System.out.println(k + " : " + Arrays.toString(v))); + + + filterChain.doFilter(servletRequest,servletResponse); + } +} diff --git a/src/main/java/org/example/je/jdbc/filter/UnsaveFilter.java b/src/main/java/org/example/je/jdbc/filter/UnsaveFilter.java new file mode 100644 index 0000000..c193d85 --- /dev/null +++ b/src/main/java/org/example/je/jdbc/filter/UnsaveFilter.java @@ -0,0 +1,22 @@ +package org.example.je.jdbc.filter; + +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.example.je.jdbc.dto.UserDto; + +import java.io.IOException; + +@WebFilter("/admin") +public class UnsaveFilter implements Filter { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + var user = (UserDto) ((HttpServletRequest) servletRequest).getSession().getAttribute("user"); + if(user != null){ + filterChain.doFilter(servletRequest,servletResponse); + } else { + ((HttpServletResponse) servletResponse).sendRedirect("/registration"); + } + } +} diff --git a/src/main/java/org/example/je/jdbc/mapper/UserMapper.java b/src/main/java/org/example/je/jdbc/mapper/UserMapper.java new file mode 100644 index 0000000..4ba052b --- /dev/null +++ b/src/main/java/org/example/je/jdbc/mapper/UserMapper.java @@ -0,0 +1,28 @@ +package org.example.je.jdbc.mapper; + +import lombok.NoArgsConstructor; +import org.example.je.jdbc.dto.UserDto; +import org.example.je.jdbc.entity.User; + +import static lombok.AccessLevel.PRIVATE; + +@NoArgsConstructor(access = PRIVATE) +public class UserMapper implements Mapper { + private static final UserMapper INSTANCE = new UserMapper(); + + public static UserMapper getInstance(){ + return INSTANCE; + } + + @Override + public UserDto mapFrom(User user) { + return UserDto.builder() + .id(user.getId()) + .email(user.getEmail()) + .name(user.getName()) + .birthdate(user.getBirthdate()) + .role(user.getRole()) + .gender(user.getGender()) + .build(); + } +} diff --git a/src/main/java/org/example/je/jdbc/service/UserService.java b/src/main/java/org/example/je/jdbc/service/UserService.java index b224bac..3313421 100644 --- a/src/main/java/org/example/je/jdbc/service/UserService.java +++ b/src/main/java/org/example/je/jdbc/service/UserService.java @@ -2,10 +2,14 @@ package org.example.je.jdbc.service; import org.example.je.jdbc.dao.UserDao; import org.example.je.jdbc.dto.CreateUserDto; +import org.example.je.jdbc.dto.UserDto; import org.example.je.jdbc.exeption.ValidationExeption; import org.example.je.jdbc.mapper.CreateUserMapper; +import org.example.je.jdbc.mapper.UserMapper; import org.example.je.jdbc.validator.CreateUserValidator; +import java.util.Optional; + public class UserService { private static final UserService INSTANCE = new UserService(); private static final UserDao userDao = UserDao.getInstance(); @@ -32,4 +36,8 @@ public class UserService { private UserService() { } + + public Optional login(String email, String password) { + return userDao.findByIdEmailAndPassword(email, password).map(user -> UserMapper.getInstance().mapFrom(user)); + } } diff --git a/src/main/java/org/example/je/jdbc/servlet/LoginServlet.java b/src/main/java/org/example/je/jdbc/servlet/LoginServlet.java new file mode 100644 index 0000000..6eb60b3 --- /dev/null +++ b/src/main/java/org/example/je/jdbc/servlet/LoginServlet.java @@ -0,0 +1,40 @@ +package org.example.je.jdbc.servlet; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import org.example.je.jdbc.dto.UserDto; +import org.example.je.jdbc.service.UserService; +import utils.JspHelper; + +import java.io.IOException; + +@WebServlet("/login") +public class LoginServlet extends HttpServlet { + private static final UserService userService = UserService.getInstance(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher(JspHelper.getPath("login")).forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) { + userService.login(req.getParameter("email"), req.getParameter("password")) + .ifPresentOrElse(userDto -> onLoginSuccess(userDto, req, resp), ()-> onLoginFail(req, resp)); + } + + @SneakyThrows + private void onLoginFail(HttpServletRequest req, HttpServletResponse resp) { + resp.sendRedirect("/login?error&email="+req.getParameter("email")); + } + + @SneakyThrows + private void onLoginSuccess(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) { + req.getSession().setAttribute("user", userDto); + resp.sendRedirect("/flights"); + } +} diff --git a/src/main/java/org/example/je/jdbc/servlet/LogoutServlet.java b/src/main/java/org/example/je/jdbc/servlet/LogoutServlet.java new file mode 100644 index 0000000..1bcdc56 --- /dev/null +++ b/src/main/java/org/example/je/jdbc/servlet/LogoutServlet.java @@ -0,0 +1,18 @@ +package org.example.je.jdbc.servlet; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/logout") +public class LogoutServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + req.getSession().invalidate(); + resp.sendRedirect("login"); + } +} diff --git a/src/main/java/utils/ConnectionManager.java b/src/main/java/utils/ConnectionManager.java index de2d838..349d446 100644 --- a/src/main/java/utils/ConnectionManager.java +++ b/src/main/java/utils/ConnectionManager.java @@ -23,6 +23,7 @@ public final class ConnectionManager { private static void loadDriver() { try { Class.forName("org.postgresql.Driver"); + Class.forName("utils.UrlPath"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } diff --git a/src/main/java/utils/UrlPath.java b/src/main/java/utils/UrlPath.java new file mode 100644 index 0000000..a251fc9 --- /dev/null +++ b/src/main/java/utils/UrlPath.java @@ -0,0 +1,10 @@ +package utils; + +public final class UrlPath { + public static final String LOGIN = "/login"; + public static final String REGISTRATION = "/registration"; + + private UrlPath() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } +} diff --git a/src/main/webapp/WEB-INF/jsp/header.jsp b/src/main/webapp/WEB-INF/jsp/header.jsp new file mode 100644 index 0000000..93106a5 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/header.jsp @@ -0,0 +1,8 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> + + +
+ +
+
diff --git a/src/main/webapp/WEB-INF/jsp/login.jsp b/src/main/webapp/WEB-INF/jsp/login.jsp new file mode 100644 index 0000000..817cc3d --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/login.jsp @@ -0,0 +1,31 @@ +<%@ page import="org.example.je.jdbc.service.TicketService"%> +<%@ page import="org.example.je.jdbc.dto.TicketDto"%> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + +<%@ taglib prefix="c" uri="jakarta.tags.core" %> +<%@ taglib prefix="fn" uri="jakarta.tags.functions" %> + + + + Регистрация + + +

Регистрация:

+
+
+

+ +
+

+ + +
+ Register + +
+ Login or password incorrect +
+
+ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/tickets.jsp b/src/main/webapp/WEB-INF/jsp/tickets.jsp index c9805b3..24add8b 100644 --- a/src/main/webapp/WEB-INF/jsp/tickets.jsp +++ b/src/main/webapp/WEB-INF/jsp/tickets.jsp @@ -10,6 +10,7 @@ Билеты +<%@ include file="header.jsp"%>

Билеты: