一、什么是互斥登录?
如果你经常使用腾讯QQ,就会发现它的登录有如下特点:它可以手机电脑同时在线,但是不能在两个手机上同时登录一个账号
同端互斥登录,指的就是像腾讯QQ一样,在同一类型设备上只允许单地点登录,在不同类型设备上允许同时在线
二、实现想法
就是在数据库创建一个字段,然后用uuid生成一串字符,作为该字段的值,然后以此字段为值,用户id为键,形成键值对,每次登录都会将生成的uuid存入session,然后登录都会与数据库的uuid进行匹配,相同则通过,不相等则退出登录;
三、项目实现
3.1、实体类
@Data
public class User {
private Integer id;
private String pwd;
private String uuid;
}
3.2、controller层
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/go/login")
public String goLogin(){
return "Login";
}
@RequestMapping("/login")
public String chekLogin(Integer id, String pwd,HttpSession session){
User user=userService.chekLogin(id,pwd);
if (user==null){
return "Login";
}else {
//将账号存取到session中
session.setAttribute("id",id);
//吧UUid自动生成id的-替换成""
String uuid=UUID.randomUUID().toString().replace("-", "");
//将属于此id的uuid标识改为当前uuid的值
userService.update(uuid,id);
//将uuid存取到session中
session.setAttribute("uuid",uuid);
return "Index";
}
}
@RequestMapping("/demo")
@ResponseBody
public String test(){
return "成功";
}
}
3.3、拦截器
/**
* 拦截器
*/
public class UserInterceptor implements HandlerInterceptor {
private UserMapper userMapper;
public UserInterceptor(UserMapper userMapper){
this.userMapper=userMapper;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//得到一个session
HttpSession session = request.getSession();
//从session读取到刚刚存入的id
String id = session.getAttribute("id").toString();
//用刚刚得到的id去数据库取属于该id的uuid
String UUID=userMapper.getUUID(Integer.parseInt(id));
//得到刚刚存入session的uuid
String uuid = (String)session.getAttribute("uuid");
if(UUID.equals(uuid)){//对比两个uuid的值是否相同
return true;
}else {
System.out.println("拦截"+request.getRequestURI());
response.sendRedirect("/login");
response.setStatus(401);
return false;
}
}
}
3.4、过滤器
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private UserMapper userMapper;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor(userMapper))
.excludePathPatterns("/login")
.excludePathPatterns("/go/login").order(1);//设置放行的两个url
}
}