feat/add login and logout logic with filters

This commit is contained in:
Dell 2026-04-12 00:22:50 +03:00
parent 14b5d9bccf
commit b2903e087a
15 changed files with 293 additions and 3 deletions

View File

@ -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<Long, User> {
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<Long, User> {
return Optional.empty();
}
public Optional<User> 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;
}

View File

@ -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;
}

View File

@ -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<String> 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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}
}

View File

@ -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<UserDto, User> {
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();
}
}

View File

@ -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<UserDto> login(String email, String password) {
return userDao.findByIdEmailAndPassword(email, password).map(user -> UserMapper.getInstance().mapFrom(user));
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -0,0 +1,8 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<c:if test="${not empty sessionScope.user}">
<form action="${pageContext.request.contextPath}/logout" method="post">
<button type="submit">Logout</button>
</form>
</c:if>

View File

@ -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" %>
<html>
<head>
<title>Регистрация</title>
</head>
<body>
<h1>Регистрация:</h1>
<form action="/login" method="POST">
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" required><br><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" required><br><br>
<button type="submit">Login</button>
</form>
<a href="${pageContext.request.contextPath}/register">Register</a>
<c:if test="${param.error != null}">
<div style="color:red">
<span>Login or password incorrect</span>
</div>
</c:if>
</body>
</html>

View File

@ -10,6 +10,7 @@
<title>Билеты</title>
</head>
<body>
<%@ include file="header.jsp"%>
<h1>Билеты:</h1>
<ol>
<c:forEach var="ticket" items="${requestScope.tickets}">