我创建了一个简单的登录servlet,用户输入他的电子邮件和密码,它检查他是否是注册用户,然后它登录他,如果他不是它说登录失败,凭据存储在文本文件中,我不能使用数据库,代码工作完美。现在唯一的问题是,我试图阻止注册用户在3次尝试后的一段特定时间,让我们说30分钟,这是怎么做到的?
文本文件的格式如下:
<<ul>电子邮件和密码用','分隔
代码:
import java.io.*;
import java.security.Principal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
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 jakarta.servlet.http.HttpSession;
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
//int attempts = 3;
/**
*
*/
private static final long serialVersionUID = -5498866193863633001L;
/**
* HashMap to store all users credentials
*/
private final Map<String, String> credentialsPairs = new HashMap<>
();
@Override
public void init(ServletConfig config) throws ServletException {
String delimiter = ",";
String line = "";
/**
* Credentials file will be there in WEB-INF directory as it
provide secured
* access only.
*/
String credentialFile = "/WEB-INF/accounts.txt";
/**
* Read the file and prepare Map with username as key and
password as value We
* have put this code in init method as it is called once only
that will avoid
* overhead of iterating values from file for each request
*/
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
ServletContext context = config.getServletContext();
try {
/**
* Open stream of file
*/
is = context.getResourceAsStream(credentialFile);
if (is != null) {
/**
* Read the file line by line and store email as a key
and password as value
*/
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
String[] credentials = line.split(delimiter);
// credentials[0] is email and credentials[1] is
password
credentialsPairs.put(credentials[0],
credentials[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void doGet(HttpServletRequest request, HttpServletResponse
response) throws IOException, ServletException {
/**
* Get user entered credentials
*/
String userEmail = request.getParameter("email");
String userPassword = request.getParameter("password");
PrintWriter out = response.getWriter();
boolean isValidUser = false;
/**
* Get value from Map for user entered email address.
*/
String password = credentialsPairs.get(userEmail);
/**
* If User with entered email address found then we will get
password for that
* user
*/
if (password != null) {
/**
* Compare password entered by user with one that is
retrieved from file
*/
if (password.equals(userPassword)) {
isValidUser = true;
}
}
HttpSession session = request.getSession();
if (isValidUser) {
//HttpSession session = request.getSession();
session.setAttribute("email", userEmail);
request.getRequestDispatcher("welcome.jsp").include(request,
response);
//response.sendRedirect("welcome.jsp");
}
else {
int loginAttempt;
if (session.getAttribute("loginCount") == null)
{
session.setAttribute("loginCount", 0);
loginAttempt = 0;
}
else
{
loginAttempt = (Integer)
session.getAttribute("loginCount");
}
//this is 3 attempt counting from 0,1,2
if (loginAttempt >= 2 )
{
long lastAccessedTime =
session.getLastAccessedTime();
Date date = new Date();
long currentTime = date.getTime();
long timeDiff = currentTime - lastAccessedTime;
// 20 minutes in milliseconds
if (timeDiff >= 1200000)
{
//invalidate user session, so they can try
again
session.invalidate();
}
else
{
// Error message
session.setAttribute("message","You have
exceeded the 3 failed login attempt. Please try loggin
in in 20 minutes.");
}
}
else
{
loginAttempt++;
int allowLogin = 3-loginAttempt;
session.setAttribute("message","loginAttempt=
"+loginAttempt+". Invalid username or password. You have
"+allowLogin+" attempts remaining. Please try again! <br>Not a
registered cusomer? Please <a
href="register.jsp">register</a>!");
}
session.setAttribute("loginCount",loginAttempt);
}
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("index.jsp");
dispatcher.forward(request, response);
}
public void destroy() {
/**
* Free up the map
*/
credentialsPairs.clear();
}
}
您应该在credentialsPairs中再添加一个属性,例如:然后,当您检查密码时,也检查登录时间阻塞用户
在用户会话中创建对象。称之为trackLogOns。当用户第一次尝试登录但失败时,在对象上放置时间戳。另外,在对象上放置一个整数,用于跟踪用户尝试登录和失败登录的次数。每次用户登录时检查该对象的会话。如果该对象存在,但计时器大于120,则删除该会话对象并创建一个新的会话对象,然后继续执行下面的逻辑。如果对象存在且小于120,则将增加计数器并相应地执行操作。例:计数器小于3,只需增加计数器。如果计数器为3或更多,则停止用户。
如果您正在尝试这样做,而用户尚未登录,则将其放在应用程序级别或上下文作用域的变量中。然后应用程序可以跟踪它。这里有一个链接,可以帮助您了解变量根据其放置位置的范围所能存活的长度。您可能知道,也可能不知道,您可以在页面级别、请求级别、会话级别和应用程序级别将变量放入内存中。应用程序级别可能是使用最少的,但在这种情况下,我认为你需要这个级别。这里有一个链接,可以帮助你更多地了解它。
https://www.javajee.com/application-request-session-and-page-scopes-in-servlets-and-jsps