1. Обзор
В этом руководстве мы узнаем, как проверить логин пользователя и убедиться, что пользователь заполнил форму входа с действительными учетными данными и начал сеанс. Однако мы сделаем это без использования Spring Security и с использованием только JSP и сервлетов . Следовательно, нам понадобится контейнер сервлета, который может его поддерживать, например Tomcat 9.
К концу у нас будет хорошее понимание того, как все работает под капотом.
2. Стратегия настойчивости
Во-первых, нам нужны пользователи. Для простоты мы будем использовать предварительно загруженную карту. Давайте определим его вместе с нашим User
:
public class User {
static HashMap<String, User> DB = new HashMap<>();
static {
DB.put("user", new User("user", "pass"));
// ...
}
private String name;
private String password;
// getters and setters
}
3. Фильтрация запросов
Мы начнем с создания фильтра для проверки запросов без сеанса, блокируя прямой доступ к нашим сервлетам:
@WebFilter("/*")
public class UserCheckFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// ...
request.setAttribute("origin", request.getRequestURI());
if (!request.getRequestURI().contains("login") && request.getSession(false) == null) {
forward(request, response, "/login.jsp");
return;
}
chain.doFilter(request, response);
}
}
Здесь, определяя « /*
» как наш шаблон URL в @WebFilter
, все запросы сначала будут проходить через наш фильтр. Затем, если сеанса еще нет, мы перенаправляем запрос на нашу страницу входа, сохраняя источник
для последующего использования. Наконец, мы возвращаемся раньше, предотвращая обработку нашего сервлета без надлежащего сеанса.
4. Создание формы входа с помощью JSP
Чтобы создать нашу форму входа, нам нужно импортировать ядро Taglib из JSTL . Кроме того, давайте установим для атрибута сеанса значение «
false
» в нашей директиве страницы .
В результате новая сессия не создается автоматически, и мы можем иметь полный контроль:
<%@ page session="false"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
<form action="login" method="POST">
...
</form>
Затем внутри нашей формы
у нас будет скрытый ввод для сохранения источника
:
<input type="hidden" name="origin" value="${origin}">
Далее мы включим условный элемент для вывода ошибок:
<c:if test="${not empty error}">
* error: ${error}
</c:if>
Наконец, давайте добавим несколько входных
тегов, чтобы пользователь мог вводить и отправлять учетные данные:
<input type="text" name="name">
<input type="password" name="password">
<input type="submit">
5. Настройка нашего сервлета входа в систему
В нашем сервлете мы перенаправим запрос в нашу форму входа, если это GET
. И самое главное, мы проверяем логин, если это POST
:
@WebServlet("/login")
public class UserCheckLoginServlet extends HttpServlet {
// ...
}
Итак, в нашем методе doGet()
мы просто перенаправляем на наш JSP входа в систему, передавая источник
вперед:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
String referer = (String) request.getAttribute("origin");
request.setAttribute("origin", referer);
forward(request, response, "/login.jsp");
}
В нашем doPost()
мы проверяем учетные данные и создаем сеанс, передавая объект пользователя
вперед и перенаправляя его на источник
:
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
String key = request.getParameter("name");
String pass = request.getParameter("password");
User user = User.DB.get(key);
if (!user.getPassword().equals(pass)) {
request.setAttribute("error", "invalid login");
forward(request, response, "/login.jsp");
return;
}
HttpSession session = request.getSession();
session.setAttribute("user", user);
response.sendRedirect(request.getParameter("origin"));
}
В случае неверных учетных данных мы устанавливаем сообщение в нашей переменной ошибки
. В противном случае мы обновляем сеанс с помощью нашего объекта User .
6. Проверка информации для входа
Наконец, давайте создадим нашу домашнюю страницу. Он просто показывает информацию о сеансе и имеет ссылку для выхода:
<body>
current session info: ${user.name}
<a href="logout">logout</a>
</body>
Все, что делает наш домашний сервлет, — это перенаправляет пользователя
на домашнюю страницу:
@WebServlet("/home")
public class UserCheckServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
User user = (User) session.getAttribute("user");
request.setAttribute("user", user);
forward(request, response, "/home.jsp");
}
}
И вот как это выглядит:
7. Выход из системы
Чтобы выйти из системы, мы просто аннулируем текущий сеанс и перенаправляем домой . После этого наш UserCheckFilter
обнаружит запрос без сеанса и перенаправит нас обратно на страницу входа, перезапустив процесс:
@WebServlet("/logout")
public class UserCheckLogoutServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession().invalidate();
response.sendRedirect("./");
}
}
8. Заключение
В этой статье мы прошли создание полного цикла входа в систему. Мы увидели, что теперь у нас есть полный контроль над доступом к нашим сервлетам с помощью одного фильтра. Короче говоря, при таком подходе мы всегда можем быть уверены, что есть действующий сеанс там, где он нам нужен. Точно так же мы могли бы расширить этот механизм, чтобы реализовать более тонкий контроль доступа.
И, как всегда, исходный код доступен на GitHub .