在spring-boot应用程序中,一次只能有一个用户使用某个页面(我们称之为home.jsp
(。如果其他用户在访问同一个url时出现,则应将其重定向到不同的页面(我们称之为another_home.jsp
(。用户不登录,只按原样使用应用程序。任何策略都可以用于home.jsp
,可以是先到先得或其他任何策略。
如果一次有多个用户在使用应用程序,那么只有一个用户应该使用home.html,其他所有用户都应该使用another_home.jsp
。
由于应用程序中不需要登录,我认为我需要匿名会话。此外,会话需要在一段时间处于非活动状态后过期。我搜索了春季安保,但什么也找不到。
我认为您甚至不需要spring安全性。简单的http会话也可以。据我所见,您只想将流分配给一个用户,为此,您需要第一个用户的会话id,每当请求再次出现时,您可以将其进行比较。因此,存储会话id,并在某个Time
对象或Date
对象超时后过期。
属性内
server.servlet.session.timeout = 600 // 10 minutes
像这样的
private String currSessionId = null;
private Date lastDate = new Date();
private Integer TIMEOUT = 600000; // 10 minutes
public String loadHomePage(Model model) {
if(currSessionId!=null && new Date().getTime()- lastDate.getTime()>TIMEOUT){
currSessionId = null;
}
if(currSessionId==null){
currSessionId = session.getId();
lastDate = new Date();
return "home";
}else{
if(session.getId().equals(currSessionId)){
return "home";
}else{
return "another_home";
}
}
}
这很简单,因为当你没有登录的用户要管理,也不需要记住用户上次停止的状态时。如果有帮助,请告诉我。
您需要创建一个服务器端状态,该状态要么为空,要么存储当前正在声明/home.jsp
的访问者的标识符。这可以是单例Bean上的字段,也可以是数据库中的实体。它必须自动过期,否则将永远阻止新访客提出索赔。只要状态为空,第一个访问者标识符就会存储在此状态中。从那一刻起,您将把所有其他访问者重定向到another_home.jsp
所以控制器代码应该类似于这个
if(visitorHoldsTheClaim()) {
return "home.jsp"
} else if (noClaimActive()) {
createClaimForVisitor();
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
根据您的实现,这些方法将执行不同的操作。
我通常建议不要使用服务器端会话状态(更多信息请参阅Roy Fieldings论文(,但是对于您的用例,您需要一种方法来识别多个请求中的访问者。一次会议肯定是实现这一目标的一种非常简单的方式。您至少可以通过一次只创建一个会话来最大限度地减少会话使用量,该会话是为持有声明的访问者创建的。在这种情况下,您永远不会有超过一个打开的会话,而拥有会话的访问者就是持有索赔的访问者。
因此,在这种情况下,实现将是这样的:
if(currentUserHasASession()) { // checks if the current user has a session, but !!!does not create a new session if it does not exist!!! careful, HttpServletRequest.getSession(true) would create it!
return "home.jsp"
} else if (serverHasNoSessions()) { // https://stackoverflow.com/questions/49539076/how-can-i-get-a-list-of-all-sessions-in-spring
createSessionForUser(); // HttpServletRequest.getSession(true)
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
请记住,只有在不在其他地方创建会话的情况下,这才有效。因此,您必须将Spring Boot/Spring Security配置为不创建会话。如何使spring-boot从不发布会话cookie?
还要记住并发性。例如,如果您只有一个服务器实例,则可以将此代码放入synchronized
方法中,以避免两个访问者同时创建声明。
所以。。。首先,这听起来是个坏主意。我很好奇你为什么需要这样不同寻常的行为。可能有更明智的方法。
正如Gregor所说,重定向代码部分相当简单:
if(pageLock.getUser() == null) {
pageLock.setUser(user);
}
if(user.equals(pageLock.getUser())) {
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
实际上更棘手的是当";到期";锁。用户很可能会简单地关闭浏览器而不点击";注销";(或其他什么(,永远离开锁。另一方面,用户可能会去午休,但其浏览器仍会打开页面数小时。
所以这是你想添加的第一件事:在页面上添加一些保持活动的机制,定期延长锁,以及一些过期检查器,如果在一段时间内没有收到任何消息,就会释放锁。
。。。但正如我一开始所说,整件事听起来很可疑。