javaweb实现单点登录,防止重复登录,获取sessionid,对session及时销毁回收,只允许一个用户登录,结合struts2实现

首先我们目的是实现一个单点登录,即只允许单个账户单个登录。

实现异地与同地登录判断

要将先登录的用户强制下线。不免用到session。

单点登录的最大难题:已经登录且重复登录的用户的session怎么web全局操作它

我们来解决它。
基本目的实现的方法之一是{
1.建立一个可以全局存储当前登录人员信息的Map;推荐hashmap,因为更快。
2.建立一个登录人员监听,}
怎么建立全局呢还记得jsp的内置对象application吗,对,就是用它。
使用session的getservetContext()可以得到
它是存在于整个web项目的,只有项目关闭时才会实现,做全局很合适
具体代码在最后
存储哪些属性呢:
1.每个用户的账户(最好必须是
唯一标识
),当做Map的key;
2.每个用户产生的session的id,好吧,可以直接存session对象的,我试过,可以当做Map的value

那么存session对象的好处是什么?你不用拿着session的id去找回session(这步超级麻烦,然而好像网上依旧有许多这样的教程)
就可以直接对已经登录的重复的session进行操作,过程仅仅需要一个强制转化, 直接解决了单点登录的最大问题:已经登录且重复登录的用户的session直接可操作

那么又来了,直接存session没有缺点吗,不可能,你想一个session有可能存着许多的变量,那么这个对象就会变得比较大,如果项目上了级别,耗费资源也是要考虑的

好现在是具体的代码,两部分
1
这是在登录验证的时候的代码,取其精华!强制转换,重复的session获取
即在登录时检查重复登录,当前在线人数及其会话,加入到全局Map

private void query(String sql) {
		try {
			Connection co = Jdbc_DBCP_xiu.getConnection();
			PreparedStatement p = co.prepareStatement(sql);
			ResultSet result = p.executeQuery();
			// 设置登录结果
			if (result.next()) {
				ActionContext.getContext().getSession().put("user", u);
				this.loginflag = true;
				// 获取session
				HttpSession session = ServletActionContext.getRequest().getSession(true);

				// 检查重复登录key_user value_session
				ServletContext application = session.getServletContext();
				@SuppressWarnings("unchecked")
				Map login_map_session = (Map) application
						.getAttribute("login_map_session");
				// hashmap查找更快
				if (login_map_session == null) {
				
					login_map_session = new HashMap<>();
				}
				for (String key : login_map_session.keySet()) {
					// 同时在线
					if (u.equals(key)) {
						// 可尝试,发送信息给未下线的另一用户或强制下线另一用户
						HttpSession otherSession=((HttpSession) (login_map_session.get(key)));// 另一用户(HttpSession) login_map_session.get(key)
						//登录失败
						this.loginflag = false;
						if (session.getId().equals(otherSession.getId())) {
							session.setAttribute("tiplogin", "该用户同一地方多次登录!其已被强制下线");
							//强制本地(同一浏览器)所有重复会话直接下线(一个不留)
							//这三句相当于删除了session
							login_map_session.remove(session.getAttribute("user"));
							session.removeAttribute("user");
							session.getServletContext().setAttribute("login_map_session", login_map_session);
							//实际不下线,留下谁都行
						} else {
							session.setAttribute("tiplogin", "该用户已经在其他地方登录!其已被强制下线");
							//强制异地(不一浏览器)重复会话直接下线
							otherSession.invalidate();
						}
						
						return;
					}
				}
				// 当前在线人数及其会话,加入到全局
				login_map_session.put(u, session);
				application.setAttribute("login_map_session", login_map_session);
				// 当前预备下线

			} else {
				this.loginflag = false;
			}
			Jdbc_DBCP_xiu.release(co, p, result);
		} catch (Exception e1) {
			// TODO 自动生成的 catch 块
			this.loginflag = false;
			
		}

	}

2.session的监听器,实现SessionListener,session登录失效去全局Map中删除

package servlet.listener;

import java.util.Map;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;

@WebListener()
public class LoginListener implements javax.servlet.http.HttpSessionListener {
/**
	 * @author joker
	 * 
	 *  
	 *  登出,map的session删除
	 */

	public void sessionCreated(HttpSessionEvent se) {
		// TODO 自动生成的方法存根
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO 自动生成的方法存根
		HttpSession s = se.getSession();
		// 保存到整个web中
		//登出
		if (s.getAttribute("user") != null) {
			@SuppressWarnings("unchecked")
			Map login_map_session = (Map) s.getServletContext().getAttribute("login_map_session");
			login_map_session.remove(s.getAttribute("user"));
			s.getServletContext().setAttribute("login_map_session", login_map_session);
		} 
	}
}

再加一点自己的前端,爽歪歪

你可能感兴趣的:(javaweb实现单点登录,防止重复登录,获取sessionid,对session及时销毁回收,只允许一个用户登录,结合struts2实现)