仅仅思路,这是springsecurety的
package com.dbapp.fly.config.security;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.dbapp.fly.entity.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
//登录用户认证通过后,显示登录成功页面前,做的操作。
@Component
public class MyAuthenctiationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(MyAuthenctiationSuccessHandler.class);
// key为sessionId,value为HttpSession,使用static,定义静态变量,使之程序运行时,一直存在内存中。
// 保存所有已经登录用户的会话(每个浏览器一个会话)
public static HashMap<String, HttpSession> sessionMap = new HashMap<String, HttpSession>();
@Autowired
// @Qualifier("sessionRegistry")
private SessionRegistry sessionRegistry;
// @Bean(name="sessionRegistry",value="sessionRegistry")
@Bean
// @Bean(name="sessionRegistry")
public SessionRegistry getSessionRegistry() {
return new SessionRegistryImpl();
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
// 1.登录认证成功后,获取用户名
//(只能在认证成功通过后,才能获得sc,不然在CustomUserService implements UserDetailsService的loadUserByUsername方法中是第二次才能获取到)
SecurityContext sc = SecurityContextHolder.getContext();
String currentuser = ((SysUser) sc.getAuthentication().getPrincipal()).getUserName();
logger.info("当前登录用户:" + currentuser);
// 2.先判断用户是否重复登录
Iterator<Entry<String, HttpSession>> iterator = sessionMap.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<String, HttpSession> entry = iterator.next();
HttpSession session = entry.getValue();
// 2.1 判断session中所包含的用户名称是否有当前登录用户
String username = SessionUtil.getUserName(session);
if (currentuser.equals(username)) {
logger.info("用户:" + currentuser + "已经在其它地方登录过,将踢除!");
SessionUtil.expireSession(session);
logger.info("删除的会话:"+entry.getKey());
// 2.2 从sessionMap中踢除会话
iterator.remove();
// 2.3 从sessionRegistry中踢除会话
sessionRegistry.removeSessionInformation(session.getId());
}
}
/*//以下这种方法会引起java.util.ConcurrentModificationException: null 错误, HashMap
// 2.先判断用户是否重复登录
for (Entry<String, HttpSession> entry : sessionMap.entrySet()) {
HttpSession session = entry.getValue();
// 2.1 判断session中所包含的用户名称是否有当前登录用户
String username = SessionUtil.getUserName(session);
if (currentuser.equals(username)) {
logger.info("用户:" + currentuser + "已经在其它地方登录过,将踢除!");
SessionUtil.expireSession(session);
logger.info(entry.getKey());
sessionMap.remove(entry.getKey());//这里会引起同步错误
sessionRegistry.removeSessionInformation(session.getId());
}
}*/
// 3.将当前session保存到sessionMap中
logger.info("将当前会话:" + request.getSession().getId() + ",保存到sessionMap");
sessionMap.put(request.getSession().getId(), request.getSession());
for (Entry<String, HttpSession> entry : sessionMap.entrySet()) {
logger.info("显示已经保存的sessionMap:Key: " + entry.getKey() + " Value: " + entry.getValue());
}
// 4.打印所有认证通过的用户(包含重复登录的,不过上面已经踢除了)
List<Object> principals = sessionRegistry.getAllPrincipals();
List<String> usersNamesList = new ArrayList<String>();
for (Object principal: principals) {
if (principal instanceof SysUser) {
usersNamesList.add(((SysUser) principal).getUserName());
}
}
logger.info("已经认证通过的用户数:"+usersNamesList.size()+", 已经认证通过用户:"+usersNamesList.toString());
// response.sendRedirect("/");
super.onAuthenticationSuccess(request, response, authentication);
}
}
package com.dbapp.fly.config.security;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//启动类加上注解@ServletComponentScan,这样才能扫描到监听器
//@WebListener
public class MySessionListner implements HttpSessionListener {
private static final Logger logger = LoggerFactory.getLogger(MySessionListner.class);
/**
* 新建session时(打开浏览器访问登录页面时,服务器会创建一个新的session)
*/
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("创建session");
}
/**
* 删除session时(退出系统)
*/
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
logger.info("销毁session时");
MyAuthenctiationSuccessHandler.sessionMap.remove(httpSessionEvent.getSession().getId());
}
}
package com.dbapp.fly.config.security;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MywebConfig implements WebMvcConfigurer {
@Bean
public ServletListenerRegistrationBean listenerRegist() {
ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
srb.setListener(new MySessionListner());
System.out.println("listener");
return srb;
}
}
package com.dbapp.fly.config.security;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.dbapp.fly.entity.SysUser;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.User;
public class SessionUtil {
private static SecurityContext attribute;
/**
* 根据当前session获取当前登录用户对象
* @param session
* @return guser
*/
public static SysUser getUser(HttpSession session) {
try {
attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();
return principal;
} catch (Exception e) {
}
return null;
}
/**
* 根据当前session获取当前登录用户ID
* @param session
* @return guser
*/
public static Long getUserId(HttpSession session) {
try {
attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();
return principal.getId();
} catch (Exception e) {
}
return null;
}
/**
* 根据session获取用户名称
* @param session
* @return void
*/
public static String getUserName(HttpSession session) {
try {
attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();
return principal.getUserName();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据session获取count
* session中包含一个count键默认为null,可以用来统计登录次数
* @param session
* @return void
*/
public static void count(HttpSession session) {
ServletContext context = session.getServletContext();
System.out.println("sessionid:"+session.getId()+",的count是:"+context.getAttribute("count"));
}
/**
* 辨别用户是否已经登录,如果已经登录就不能登录了。
*
* @param request
* @param sessionRegistry
* @param loginedUser
*/
public static void deleteSameUser(HttpServletRequest request, SessionRegistry sessionRegistry, User loginedUser) {
SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
List<SessionInformation> sessionsInfo;
sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), true);
String currentSessionId;
if (null != sessionsInfo && sessionsInfo.size() == 0) {
sessionRegistry.registerNewSession(request.getSession().getId(), sc.getAuthentication().getPrincipal());
sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);
}
currentSessionId = sessionsInfo.get(0).getSessionId();
List<Object> o = sessionRegistry.getAllPrincipals();
for (Object principal : o) {
if (principal instanceof User && (loginedUser.getUsername().equals(((User) principal).getUsername()))) {
List<SessionInformation> oldSessionsInfo = sessionRegistry.getAllSessions(principal, false);
if (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) {
for (SessionInformation sessionInformation : sessionsInfo) {
//当前session失效
sessionInformation.expireNow();
sc.setAuthentication(null);
sessionRegistry.removeSessionInformation(currentSessionId);
//throw new GeneralServerExistException(ErrorMessage.ALONG_LOGIN_ERROTR.toString());
}
}
}
}
}
/**
* 会话销毁(剔除前一个用户)
*
* @param , SysMessageService sysMessageService
*/
public static void expireSession(HttpSession session) {
session.invalidate();
}
/**
* 剔除前一个用户
*
* @param request
* @param sessionRegistry
* @param loginedUser
* @param , SysMessageService sysMessageService
*/
public static void dropPreviousUser2(HttpServletRequest request, SessionRegistry sessionRegistry, SysUser loginedUser) {
List<SessionInformation> sessionsInfo = null;
//登录以后session里才会加入键名为"SPRING_SECURITY_CONTEXT"的字段
SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
if(sc!=null) {
System.out.println("!!!!!!!!!!!!"+sc.getAuthentication().getPrincipal().toString());
//获取当前登录用户的会话信息集合
sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);
if (sessionsInfo.size() > 0) {
//当前会话ID
String currentSessionId = sessionsInfo.get(0).getSessionId();
//获取所有已经登录的用户
List<Object> o = sessionRegistry.getAllPrincipals();
for (Object principal : o) {
//当登录用户的名字和已经登录用户的名字相同,也就是登录用户已经登录过了。
if (principal instanceof User && (loginedUser.getUserName().equals(((User) principal).getUsername()))) {
//获取已经登录用户的会话信息集合
List<SessionInformation> oldSessionsInfo = sessionRegistry.getAllSessions(principal, false);
//如果会话信息不为空且会话信息的ID不等于当前会话ID
if (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) {
//遍历已经登录用户的会话信息,并设置过期,即删除session
for (SessionInformation sessionInformation : oldSessionsInfo) {
//旧用户的session失效
//send message
//sysMessageService.sendMessage(((User) principal).getUsername(), new SysMessage(null, Consts.NOTIFICATION_TYPE_HADLOGIN_CONTENT, 5, Consts.NOTIFICATION_ACCEPT_TYPE_HADLOGIN));
sessionInformation.expireNow();
}
}
}
}
}
}
}
/**
* session 失效
*
* @param request
* @param sessionRegistry
*/
public static void expireSession(HttpServletRequest request, User user, SessionRegistry sessionRegistry) {
List<SessionInformation> sessionsInfo = null;
if (null != user) {
List<Object> o = sessionRegistry.getAllPrincipals();
for (Object principal : o) {
if (principal instanceof User && (user.getUsername().equals(((User) principal).getUsername()))) {
sessionsInfo = sessionRegistry.getAllSessions(principal, false);
}
}
} else if (null != request) {
SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
if (null != sc.getAuthentication().getPrincipal()) {
sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);
sc.setAuthentication(null);
}
}
if (null != sessionsInfo && sessionsInfo.size() > 0) {
for (SessionInformation sessionInformation : sessionsInfo) {
//当前session失效
sessionInformation.expireNow();
sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
}
}
}
public void showsession(HttpServletRequest request) {
//获取session
HttpSession session = request.getSession();
// 获取session中所有的键值
Enumeration<String> attrs = session.getAttributeNames();
// 遍历attrs中的
while(attrs.hasMoreElements()){
// 获取session键值
String name = attrs.nextElement().toString();
// 根据键值取session中的值
Object vakue = session.getAttribute(name);
// 打印结果
System.out.println("--sessionID"+session.getId());
System.out.println("--名字:" + name +"-----\n");
System.out.println("--值:" + vakue +"--------\n");
}
}
}