本方法因为是根据思路纯手写,代码可以再简化,功能尝试没问题,最主要就是在登陆验证中的逻辑,checkLogin()方法是登录前的验证,而真正的登陆方式采用的是Shiro,若不是采用Shiro登陆,将该逻辑采用到自己登陆的方法中即可实现
一、用户验证必须字段 用户实体类中User.java添加一下字段,可自选持久化工具,本次采用jpa作为持久化工具
除了用户id,账户,密码之外其中还必须有三个字段lastLoginErrorTime最后一次登陆错误时间、loginErrorcount登陆错误计数、isLocked是否锁定(0、未锁定;1、锁定)
@Entity
@Table(name = "user_info")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserInfo implements Serializable{
private static final long serialVersionUID = 1L;
/**
* 用户模式(0,为管理员;1,为普通用户)
*/
@Column
private Integer userModel=1;//默认为普通用户
//public static enum UserType {
//SUPER, NORMAL
//}
/**
* 主键
*/
@Id
@Column(name = "user_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;
/**
* 登录帐号
*/
@Column//(unique = true)
private String userName;
/**
* 用户密码
*/
@Column
private String password="";
/**
* 角色对应外键
*/
@Column
private Integer roleId;
/**
* 部门对应外键
*/
@Column
private Integer departmentId;
/**
* 添加时间
*/
@Column
private Date addTime;
/**
* 最后一次登录时间
*/
@Column
private Date lastLoginTime;
/**
* 最后一次登陆错误时间
*/
@Column(name = "last_login_error_time",columnDefinition="DATETIME COMMENT '最后一次登陆错误时间'")
private Date lastLoginErrorTime;
/**
* 登陆错误计数
*/
@Column(name = "login_rrror_count",columnDefinition="DATETIME COMMENT '登陆错误计数'")
private Integer loginErrorcount;
/**
* 是否锁定(0、未锁定;1、锁定)
*/
@Column(name = "is_locked",columnDefinition="DATETIME COMMENT '是否锁定'")
private Integer isLocked;
// get/set方法此处省略
}
二、对应数据库
三、登陆方法中进行判断验证out.print()打印的是前台接收的Json字符串
/**
* 检查登录是否正确并判断登录项目
*
* @throws IOException
*/
public void checkLogin() throws IOException {
StatusPrinter.print(lc);
HttpServletResponse response = ServletActionContext.getResponse();
response.setCharacterEncoding(DEFAULT_CHARACTER_UTF8);
PrintWriter out = response.getWriter();
HttpSession session = ServletActionContext.getRequest().getSession();
// 得到系统保存的验证码
String valiCode = (String) session.getAttribute("rand");
if (valiCode == null) {
out.print("{\"result\":\"验证码失效,请刷新页面后重试。\",\"msg\":\"系统错误,刷新后重试。\"}"); // 刷新登录
out.flush();
out.close();
return; // 返回结束;
}
// 如果验证码错误
if (!valiCode.equals(rand)) {
out.print(ActionResult.ErrMsg("验证码错误。")); // 刷新登录
out.flush();
out.close();
return; // 返回结束;
}
UserInfo user = userService.getUserByUserName(username);
Date thisErrorLoginTime = null;// 修改的本次登陆错误时间
Integer islocked = 0;// 获取是否锁定状态
if (user == null) {// 账号密码有问题
out.print(ActionResult.ErrMsg("不存在此用户"));
} else if (user.getStatus()==1) {
out.print(ActionResult.ErrMsg("此用户已被删除"));
} else if (!user.getPassword().equals(MD5.getMD5(password.getBytes()))) {
if (user.getIsLocked() == null) {
user.setIsLocked(0);
} else {
islocked = user.getIsLocked();
}
if (user.getLoginErrorcount() == null) {
user.setLoginErrorcount(0);
}
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datestr = format.format(date);
try {
thisErrorLoginTime = format.parse(datestr);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (islocked == 1) {// 账户被锁定 // 被锁定是登陆错误次数一定是5,所以只判断一次
Date lastLoginErrorTime = null; // 最后一次登陆错误时间
Long timeSlot = 0L;
if (user.getLastLoginErrorTime() == null) {
lastLoginErrorTime = thisErrorLoginTime;
} else {
lastLoginErrorTime = user.getLastLoginErrorTime();
timeSlot = thisErrorLoginTime.getTime() - lastLoginErrorTime.getTime();
}
if (timeSlot < 1800000) {// 判断最后锁定时间,30分钟之内继续锁定
out.print(ActionResult.ErrMsg("您的账户已被锁定,请" + (30-Math.ceil((double)timeSlot/60000)) + "分钟之后再次尝试"));
} else {// 判断最后锁定时间,30分钟之后仍是错误,继续锁定30分钟
user.setLastLoginErrorTime(thisErrorLoginTime);
userService.addUser(user);
out.print(ActionResult.ErrMsg("账户或密码错误,您的账户已被锁定,请30分钟之后再次尝试登陆"));
}
} else if (user.getLoginErrorcount() == 4) {// 账户第五次登陆失败 ,此时登陆错误次数增加至5,以后错误仍是5,不再递增
user.setLoginErrorcount(5);
user.setIsLocked(1);
user.setLastLoginErrorTime(thisErrorLoginTime);
userService.addUser(user);//修改用户
out.print(ActionResult.ErrMsg("您的账户已被锁定,请30分钟之后再次尝试登陆"));
} else {// 账户前四次登陆失败
user.setLoginErrorcount(user.getLoginErrorcount() + 1);
user.setLastLoginErrorTime(thisErrorLoginTime);
userService.addUser(user);//修改用户
out.print(ActionResult.ErrMsg("账户或密码错误,您还有" + (5-user.getLoginErrorcount()) +"次登陆机会"));
}
} else {
islocked = user.getIsLocked();
if (islocked == 1) {
Date lastLoginErrorTime = null; // 最后一次登陆错误时间
Long timeSlot = 0L;
if (user.getLastLoginErrorTime() == null) {
lastLoginErrorTime = new Date();
} else {
lastLoginErrorTime = user.getLastLoginErrorTime();
timeSlot = new Date().getTime() - lastLoginErrorTime.getTime();
}
if (timeSlot < 1800000) {// 判断最后锁定时间,30分钟之内继续锁定
out.print(ActionResult.ErrMsg("您的账户已被锁定,请" + (30-Math.ceil((double)timeSlot/60000)) + "分钟之后再次尝试"));
} else {// 判断最后锁定时间,30分钟之后登陆账户
RoleInfo r=roleService.getRoleById(user.getRoleId());
if(r.getStatus()==1){
out.print("{\"result\":\"该用户拥有的角色已被管理员删除,请于管理员联系。\"}");
}else{
session.setAttribute("user", user);// 保存当前用户
Date d=new Date();
session.setAttribute("dateStr", d); // 保存当前用户登录时间用于显示
user.setLoginErrorcount(0);
user.setIsLocked(0);
user.setLastLoginTime(user.getLoginTime());
user.setLastLoginIp(user.getLoginIp());
user.setLoginTime(d);
user.setLoginIp(ServletActionContext.getRequest().getRemoteAddr());
userService.addUser(user);//修改用户表登录时间
// logService.addOperationLog("登录系统");
log.info("登录系统");
out.print(ActionResult.SUCCESS);
}
}
} else {
RoleInfo r=roleService.getRoleById(user.getRoleId());
if(r.getStatus()==1){
out.print("{\"result\":\"该用户拥有的角色已被管理员删除,请于管理员联系。\"}");
}else{
session.setAttribute("user", user);// 保存当前用户
Date d=new Date();
session.setAttribute("dateStr", d); // 保存当前用户登录时间用于显示
user.setLoginErrorcount(0);
user.setIsLocked(0);
user.setLastLoginTime(user.getLoginTime());
user.setLastLoginIp(user.getLoginIp());
user.setLoginTime(d);
user.setLoginIp(ServletActionContext.getRequest().getRemoteAddr());
userService.addUser(user);//修改用户表登录时间
// logService.addOperationLog("登录系统");
log.info("登录系统");
out.print(ActionResult.SUCCESS);
}
}
}
out.flush();
out.close();
}
四、实现的逻辑
原文链接:https://blog.csdn.net/weixin_41996632/article/details/85675410
相关推荐
【Java GUI界面登陆验证系统详解】 Java GUI(图形用户界面)是Java编程中用于创建桌面应用程序的一种方式,它允许用户通过图形元素与程序交互。在本项目中,我们利用Java的SWING库来构建登录验证系统,这涉及到...
主要介绍了Java中SpringSecurity密码错误5次锁定用户的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
总的来说,理解并实现这样的登录验证代码对于学习Java编程和网络安全基础是非常有价值的。通过不断地实践和学习,你可以构建更安全、功能更完善的用户认证系统。如果你在阅读本文或尝试编写类似代码时遇到问题,欢迎...
这可以通过增加一个“登录错误次数”字段来实现。每次登录失败,这个字段的值就加一。一旦达到预设的阈值,系统会更新一个“账户锁定时间”字段,设置为当前时间加上24小时,表示账户被锁定一天。在此期间,用户无法...
要实现多次登录失败账户锁定的功能,我们需要先回顾一下基础知识:Spring Security 不需要我们自己实现登录验证逻辑,而是将用户、角色、权限信息以实现 UserDetails 和 UserDetailsService 接口的方式告知 Spring ...
下面是一个简单的Java短信验证码获取次数限制实例的实现代码: ```java public class SmsCodeLimit { private static final int MAX_TIMES = 5; // 最大获取次数 private static final int TIME_INTERVAL = 60; //...
在Java编程中,连接数据库以实现用户登录功能是一项基础但重要的任务。这通常涉及到数据库的交互,如查询、验证用户凭据等。本教程将详细解释如何使用Java连接Oracle数据库来实现这一功能。 首先,我们需要了解Java...
本项目以纯Java代码实现了一个简单的用户登录与注册功能,不含图形用户界面(GUI)的图片资源,而是通过源码直接展示逻辑。 首先,我们需要创建一个用户类(User)来存储和管理用户信息。这个类通常包含用户名...
在本项目中,我们将利用Java的基础知识,包括循环、双重循环和随机数生成,来创建一个幸运抽奖系统。这个系统分为五个主要阶段,逐步构建出一个完整的交互式应用。 阶段1:实现菜单的输出显示 在这一阶段,我们需要...
在Java中调用C代码可能需要用到JNI(Java Native Interface),这是一组接口和工具,允许Java代码和其他语言写的代码进行交互。JNI使得Java能够调用C/C++的库,但也增加了复杂性,因为需要处理多语言间的内存管理和...
4. **错误重试机制**:为了增加安全性,通常会限制用户连续错误尝试的次数,超过次数则锁定账户或等待一段时间后重试。 5. **加密存储**:用户的密码路径不应该以明文形式保存,需要进行加密处理,确保数据安全。...
在实现这些功能时,Java提供了强大的类库支持,比如`java.util.Scanner`用于用户输入,`java.security`包可以用来处理加密,`java.sql`用于数据库交互,以及`java.swing`或`javafx`构建图形用户界面。开发过程中,...
- PIN验证是保障交易安全的重要环节,每次PIN验证失败都会减少剩余尝试次数,达到一定次数后,钱包会被锁定,防止非法访问。 7. **实验总结** 通过这个实验,学生可以深入了解Java卡应用开发的过程,掌握智能卡...
**JSP登陆系统详解** 在Web开发中,JavaServer Pages(JSP)是用于创建动态网页的一种技术。在这个"JSP登陆系统"中,我们涵盖了登陆界面、处理界面、成功界面、失败界面以及注销界面这五个关键部分。下面将详细阐述...
否则,提示错误并可能锁定用户尝试次数。 7. **超时机制**:验证码通常有有效期,比如5-15分钟,过期后需要重新获取。这是为了防止用户长时间未操作导致验证码被他人截获。 8. **异常处理**:开发过程中需要考虑...
本文将深入探讨有验证码的登录代码的相关知识点,包括验证码的原理、实现方式以及如何将其整合到登录系统中。 验证码(CAPTCHA)全称为“全自动区分计算机和人类的图灵测试”(Completely Automated Public Turing ...
总的来说,“登陆出错信息反馈”项目关注的是登录验证过程中错误处理和用户体验的提升,这对于任何需要用户认证的系统都是至关重要的。通过有效的错误反馈,不仅可以帮助用户解决问题,还能增强系统的整体安全性和...
Eclipse是一款流行的Java集成开发环境,熟练使用Eclipse可以方便地编写、运行和调试Java代码。 2. **循环控制结构**:项目中用到了`for`、`while`和`do-while`循环,这些是Java中控制程序流程的重要工具。例如,在...
7. **错误尝试限制**:为了增加安全性,通常会限制用户连续错误尝试的次数,超过次数后可能会锁定账户或显示验证码。 在"GesturePasswordManager-master"这个项目中,你可能会看到以下文件结构: - `...
6. **变量和计数器**:`int count = 3` 初始化了尝试次数为3,每次输入错误,`count--` 减少一次尝试次数。 7. **方法调用**:在`main1()` 方法中,调用了`fac()` 方法来执行密码登录逻辑。这展示了方法的封装和...