闲来无事,想起来之前解决的问题还未曾做笔记,借此时机,对前一阶段的工作做一个总结。刚接手这个项目的时候,任何用户在任何地点任何时间都可以使用同一个账户登录,这让我很恼火,完全不符合设计要求,于是,决定对其进行改善。这是我实现单点登录的代码:
功能一
单点登录实现机制:
当用户A使用账号a在浏览器中登录时,若用户B在另一台电脑上也用a账号登录,当用户B进行登录验证时,将会出发登录监听器,在监听类中判断a账号已被用户A登录,此时就会提示用户B(a账号已被登录)。
代码实现:
在实现过程中,用到SessionListener监听类、login登录方法以及web.xml配置监听类。
SessionListener类:
import java.util.HashMap;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.apache.log4j.Logger;
public class SessionListener implements HttpSessionListener {
private static final Logger logger = Logger
.getLogger(SessionListener.class);
private static HashMap hUserName = new HashMap(); // 保存sessionID和username的映射
public void sessionCreated(HttpSessionEvent se) {
}
public void sessionDestroyed(HttpSessionEvent se) {
hUserName.remove(se.getSession().getId());
}
/**
* isAlreadyEnter-用于判断用户是否已经登录以及相应的处理方法
*
* @param sUserName
* String-登录的用户名称
* @return boolean-该用户是否已经登录过的标志
*/
public static Boolean isAlreadyEnter(HttpSession session, String sUserName) {
boolean flag = false;
if (hUserName.containsValue(sUserName)) {// 如果该用户已经登录过,则提示用户已登录(依据使用户名是否在hUserName中
flag = true;
logger.info("已登录hUserName = " + hUserName);
} else {// 如果该用户没登录过,直接添加现在的sessionID和username
flag = false;
hUserName.put(session.getId(), sUserName);
logger.info("未登录hUserName = " + hUserName);
}
return flag;
}
/**
* isOnline-用于判断用户是否在线
*
* @param session
* HttpSession-登录的用户名称
* @return boolean-该用户是否在线的标志
*/
public static boolean isOnline(HttpSession session) {
boolean flag = true;
if (hUserName.containsKey(session.getId())) {
flag = true;
} else {
flag = false;
}
return flag;
}
}
登录方法:
对账号、密码、验证码进行判断和验证,并对该用户是否已登录进行验证,代码如下:
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import cn.mdsd.admin.domain.User;
@Controller
@RequestMapping("/login/")
public class loginController {
/**
* 登录
*
* @param userName
* @param passWord
* @param code
* 验证码
* @param type
* 登陆类型(商户,操作员)
* @return
*/
@RequestMapping(value = "/login.html", method = RequestMethod.POST)
public String login(String userName, String passWord, String code,
HttpServletRequest request) {
String message = null;
if (SessionListener.isAlreadyEnter(request.getSession(), userName)) {
message = "{'failure':true,info:'用户已登录!'}";
} else {
// 登录验证并返回登录成功用户对象
User user = loginResult(userName, passWord, code, request);
......
if (user != null) {
message = "{'failure':true,info:'登录成功!'}";
}else{
message = "{'failure':true,info:'登录失败!'}";
}
}
return message;
}
}
web.xml配置
把SessionListener监听类,配置到web.xml文件中,这样才可以生效,配置如下:
<listener>
<listener-class>cn.mdsd.admin.utils.SessionListener</listener-class>
</listener>
功能二
单点登录实现机制:
用户A使用账号a在浏览器上登录时,若用户B在另一台电脑上登录账号a,当用户B登录验证成功时,将会出发登录监听器,在监听器中判断账号a已经被用户A登录,就把用户A的账号a踢出去,此时当用户操作页面时,页面就会跳转至登录页面。
代码实现:
在实现过程中,用到SessionListener监听类、login登录方法以及web.xml配置监听类。
SessionListener类:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionListener implements HttpSessionListener {
// 保存sessionID和username的映射
private static HashMap hUserName = new HashMap();
/** 以下是实现HttpSessionListener中的方法* */
public void sessionCreated(HttpSessionEvent se) {
}
public void sessionDestroyed(HttpSessionEvent se) {
hUserName.remove(se.getSession().getId());
}
/**
* isAlreadyEnter-用于判断用户是否已经登录以及相应的处理方法
*
* @param sUserName
* String-登录的用户名称
* @return boolean-该用户是否已经登录过的标志
*/
public static boolean isAlreadyEnter(HttpSession session, String sUserName) {
boolean flag = false;
// 如果该用户已经登录过,则使上次登录的用户掉线(依据使用户名是否在hUserName中)
if (hUserName.containsValue(sUserName)) {
flag = true;
// 遍历原来的hUserName,删除原用户名对应的sessionID(即删除原来的sessionID和username)
Iterator iter = hUserName.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
if (((String) val).equals(sUserName)) {
hUserName.remove(key);
}
}
// 添加现在的sessionID和username
hUserName.put(session.getId(), sUserName);
System.out.println("hUserName = " + hUserName);
} else {// 如果该用户没登录过,直接添加现在的sessionID和username
flag = false;
hUserName.put(session.getId(), sUserName);
System.out.println("hUserName = " + hUserName);
}
return flag;
}
/**
* isOnline-用于判断用户是否在线
*
* @param session
* HttpSession-登录的用户名称
* @return boolean-该用户是否在线的标志
*/
public static boolean isOnline(HttpSession session) {
boolean flag = true;
if (hUserName.containsKey(session.getId())) {
flag = true;
} else {
flag = false;
}
return flag;
}
web.xml配置
把SessionListener监听类,配置到web.xml文件中,这样才可以生效,配置如下:
<listener>
<listener-class>cn.mdsd.admin.utils.SessionListener</listener-class>
</listener>
应用:
- 在登录验证时,调用SessionListener.isAlreadyEnter(session,userName)。既可以判断该用户名的用户是否登录过,又可以使上次登录的用户掉线。
- 其他页面调用SessionListener。isOnline(session),可以判断用户是否在线。