springboot基于redis实现用户唯一登陆
用户唯一登陆需求:要求当账号第一次被登陆时可以正常登陆,当账号在别处登陆时,将退出之前登陆。
大概流程如下:
项目启动时,首先清空之前登陆记录,防止出错。第一次登陆判断redis是否有登陆记录,没有则登陆成功。第二次登陆判断redis有登陆记录,获取之前登陆记录并删除,第二次登陆成功。
一、将redis缓存删除。
创建启动类并实现CommandLineRunner接口。首先说明我将登陆用户名作为key,sessionID作为value存入redis。记得在启动类加@ServletComponentScan注解
@Component
public class Runner implements CommandLineRunner {
private final Log logger = LogFactory.getLog(Runner.class);
@Resource
GwUserService gwUserService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 单用户登录设置
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
***//获取登陆用户名
for (int i = 0; i < list.size(); i++) {
if (redisTemplate.opsForValue().get(list.get(i))!=null){
redisTemplate.opsForValue().set(list.get(i).toString(),null);
}
}
logger.info("redis初始化用户信息完成");
}
}
二、接下来是判断是否之前有登陆记录逻辑。
String id = redisTemplate.opsForValue().get(username)+""; //存在跨域问题
SessionContext myc= SessionContext.getInstance();
if(id !=null && !"null".equals(id)){//如果获取到之前有人登录过,就将之前用户session注销
Session sess = myc.getSession(id);
sess.setAttribute("message","账号已在别处登录");
sess.setTimeout(3000);
}
myc.addSession(currentUser.getSession());
redisTemplate.opsForValue().set(username, currentUser.getSession().getId());
跨域问题下面会有说。这里面通过sessionID获取session,然后设置之前session过期时间。也可以直接调用销毁session方法。
三、通过sessionID获取session
public class SessionContext {
private static SessionContext instance;
private HashMap<String,Session> sessionMap;
private SessionContext() {
sessionMap = new HashMap<String,Session>();
}
public static SessionContext getInstance() {
if (instance == null) {
instance = new SessionContext();
}
return instance;
}
public synchronized void addSession(Session session) {
if (session != null) {
sessionMap.put(session.getId()+"", session);
}
}
public synchronized void delSession(Session session) {
if (session != null) {
sessionMap.remove(session.getId());
}
}
public synchronized Session getSession(String sessionID) {
if (sessionID == null) {
return null;
}
return sessionMap.get(sessionID);
}
}
三、跨域问题:配置类,当然也需要前端配合。
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。这里默认30天
private long maxAge = 30 * 24 * 60 * 60;
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(maxAge);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}
到此之后就可以实现唯一登陆了。同一电脑不同浏览器也是可用的哦
本文地址:https://blog.csdn.net/Dcocount/article/details/108236808