欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一个限制登陆的listener应用

程序员文章站 2022-03-09 10:54:30
...
   下面是学习时,发现书上有段不错的代码,是说只允许一台机器的一个帐号登陆的,另外一个上线的话,会被注销掉。下面是代码;



<%
String action = request.getParameter("action");
String account = request.getParameter("account");

if("login".equals(action) && account.trim().length() > 0){

  // 登录,将personInfo放入session
  PersonInfo personInfo = new PersonInfo();
  personInfo.setAccount(account.trim().toLowerCase());
  personInfo.setIp(request.getRemoteAddr());
  personInfo.setLoginDate(new java.util.Date());
 
  session.setAttribute("personInfo", personInfo);
 
  response.sendRedirect(response.encodeRedirectURL(request.getRequestURI()));
  return;
}
else if("logout".equals(action)){

  // 注销,将personInfo从session中移除
  session.removeAttribute("personInfo");
 
  response.sendRedirect(response.encodeRedirectURL(request.getRequestURI()));
  return;
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Insert title here</title>
  <style type="text/css">
  body {
   font-size:12px;
  }
  </style>
</head>
<body>
 
  <c:choose>
 
   <c:when test="${ personInfo != null }">
    <!-- 已经登录,将显示帐号信息 -->
    欢迎您,${ personInfo.account }。<br/>
    您的登录IP为${ personInfo.ip },<br/>
    登录时间为<fmt:formatDate value="${ personInfo.loginDate }" pattern="yyyy-MM-dd HH:mm"/>。
    <a href="${ pageContext.request.requestURI }?action=logout">退出</a>
   
    <!-- 每5秒钟刷新一次页面 -->
    <script>setTimeout("location=location; ", 5000); </script>
   </c:when>
  
   <c:otherwise>
    <!-- 没有登录,将显示登录页面 -->
    ${ msg }
    <c:remove var="msg" scope="session" />
    <form action="${ pageContext.request.requestURI }?action=login" method="post">
     帐号:
     <input name="account" />
     <input type="submit" value="登录">
    </form>
   </c:otherwise>
 
  </c:choose>




PersonInfo.java:



public class PersonInfo implements Serializable {

private static final long serialVersionUID = 4063725584941336123L;

// 帐号
private String account;

// 登录IP地址
private String ip;

// 登录时间
private Date loginDate;

public String getAccount() {
  return account;
}

public void setAccount(String account) {
  this.account = account;
}

public String getIp() {
  return ip;
}

public void setIp(String ip) {
  this.ip = ip;
}

public Date getLoginDate() {
  return loginDate;
}

public void setLoginDate(Date loginDate) {
  this.loginDate = loginDate;
}

@Override
public boolean equals(Object obj) {
  if (obj == null || !(obj instanceof PersonInfo)) {
   return false;
  }
  return account.equalsIgnoreCase(((PersonInfo) obj).getAccount());
}



listener.java:用MAP把登陆的session保存


public class LoginSessionListener implements HttpSessionAttributeListener {

Log log = LogFactory.getLog(this.getClass());

Map<String, HttpSession> map = new HashMap<String, HttpSession>();

public void attributeAdded(HttpSessionBindingEvent event) {

  String name = event.getName();

  // 登录
  if (name.equals("personInfo")) {

   PersonInfo personInfo = (PersonInfo) event.getValue();

   if (map.get(personInfo.getAccount()) != null) {

    // map 中有记录,表明该帐号在其他机器上登录过,将以前的登录失效
    HttpSession session = map.get(personInfo.getAccount());
    PersonInfo oldPersonInfo = (PersonInfo) session
      .getAttribute("personInfo");

    log.info("帐号" + oldPersonInfo.getAccount() + "在"
      + oldPersonInfo.getIp() + "已经登录,该登录将*下线。");

    session.removeAttribute("personInfo");
    session.setAttribute("msg", "您的帐号已经在其他机器上登录,您*下线。");
   }

   // 将session以用户名为索引,放入map中
   map.put(personInfo.getAccount(), event.getSession());
   log.info("帐号" + personInfo.getAccount() + "在" + personInfo.getIp()
     + "登录。");
  }
}

public void attributeRemoved(HttpSessionBindingEvent event) {

  String name = event.getName();

  // 注销
  if (name.equals("personInfo")) {
   // 将该session从map中移除
   PersonInfo personInfo = (PersonInfo) event.getValue();
   map.remove(personInfo.getAccount());
   log.info("帐号" + personInfo.getAccount() + "注销。");
  }
}

public void attributeReplaced(HttpSessionBindingEvent event) {

  String name = event.getName();

  // 没有注销的情况下,用另一个帐号登录
  if (name.equals("personInfo")) {

   // 移除旧的的登录信息
   PersonInfo oldPersonInfo = (PersonInfo) event.getValue();
   map.remove(oldPersonInfo.getAccount());

   // 新的登录信息
   PersonInfo personInfo = (PersonInfo) event.getSession()
     .getAttribute("personInfo");

   // 也要检查新登录的帐号是否在别的机器上登录过
   if (map.get(personInfo.getAccount()) != null) {
    // map 中有记录,表明该帐号在其他机器上登录过,将以前的登录失效
    HttpSession session = map.get(personInfo.getAccount());
    session.removeAttribute("personInfo");
    session.setAttribute("msg", "您的帐号已经在其他机器上登录,您*下线。");
   }
   map.put("personInfo", event.getSession());
  }

}




  还有一个小技巧就是:

MyContextListener implements ServletContextListener {





public void contextInitialized(ServletContextEvent event) {
  // 启动时,记录服务器启动时间
  ApplicationConstants.START_DATE = new Date();
}

public void contextDestroyed(ServletContextEvent event) {
  // 关闭时,将结果清除。也可以将结果保存到硬盘上。

}

  ServletContextListener :监听context的创建与销毁的,当服务器启动或执行war包时,执行contextInitialized,关闭时执行
contextDestroyed