本方法因為是根據思路純手寫,代碼可以再簡化,功能嘗試沒問題,最主要就是在登陸驗證中的邏輯,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();
}
四、實現的邏輯