在网上有很多解决限制登录的方法,包括springsecurity也有解决的方案,今天记录一下使用javaweb的实现
知识点
思路如下:

演示
具体实现:
1.维护一个map集合
public class loginusermap {
private static map<string, string> loginusermap = new concurrenthashmap<string, string>();
/**
* set方法
*
* @param loginid 用户唯一标识,用户名或者用户id
* @param sessionid sessionid
*/
public static void setloginusermap(string loginid, string sessionid) {
loginusermap.put(loginid, sessionid);
}
/**
* get方法
*
* @return
*/
public static map<string, string> getloginusermap() {
return loginusermap;
}
/**
* 根据sessionid移除map中的值
*
* @param sessionid
*/
public static void removeuser(string sessionid) {
for (map.entry<string, string> entry : loginusermap.entryset()) {
if (sessionid.equals(entry.getvalue())) {
loginusermap.remove(entry.getkey());
break;
}
}
}
/**
* 判断用户是否在map中
*
* @param loginid
* @param sessionid
* @return
*/
public static boolean isinloginusers(string loginid, string sessionid) {
return (loginusermap.containskey(loginid) && sessionid.equals(loginusermap.get(loginid)));
}
2.实现一个session监听
session销毁能及时更新map
@weblistener
public class sessionlistener implements httpsessionlistener {
private logger logger=loggerfactory.getlogger(sessionlistener.class);
@override
public void sessioncreated(httpsessionevent httpsessionevent) {
}
@override
public void sessiondestroyed(httpsessionevent httpsessionevent) {
httpsession session = httpsessionevent.getsession();
string sessionid = session.getid();
//session销毁时消除loginusermap中的sessionid
loginusermap.removeuser(sessionid);
logger.info("session销毁,sessionid:"+sessionid);
}
}3.定义过滤器
可自定义一个过滤器,但要排除登录请求(略),核心代码如下
//判断是否重复登录
string loginname = username.getloginname();//获取用户唯一标识
//判断当前用户session是否改变
if (!loginusermap.isinloginusers(loginname,session.getid())) {
//定义自己的实现方式,被挤下线,我的是:
//session发送改变,表示别处登录
//被挤下线,清除session,提示信息,实现跳转
request.setattribute("online",false);
request.getrequestdispatcher("/logout.do").forward(request,response);
return;
}
chain.dofilter(new xsshttpserlet((httpservletrequest) request), response);4.注册监听和过滤器
<filter>
<filter-name>loginlimitfilter</filter-name>
<filter-class>io.github.brightloong.loginlimite.loginlimitfilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginlimitfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>另外,可以设置轮询的方式判断,让用户及时下线,但消耗资源,我采取的是请求失败跳转的方式,直接调用退出登录的接口
总结
实现无法解决同一浏览器多次登录的问题,及sessionid相同,但能实现基本的限制登录的操作,因为做的是踢线下,所以相比账号在线,无法登录来说,稍微简单,若做第二种形式,则需要考虑session是否消除的问题。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论