首页 > 解决方案 > 一次只有一个用户使用整个 Web 应用程序 - Spring Boot

问题描述

在 Spring Boot 应用程序中,一次只有一个用户应该使用某个页面(我们称之为home.jsp)。another_home.jsp如果其他用户在访问相同的 url 时出现,则应将其重定向到不同的页面(我们称之为)。用户没有登录,只是按原样使用应用程序。任何可以使用的策略都可以home.jsp是先到先服务或任何其他策略。

如果有多个用户同时使用应用程序,则只有一个用户应该使用 home.html,而其他所有用户都应该使用another_home.jsp.

由于应用程序中不需要登录,我相信我需要匿名会话。此外,会话需要在一段时间不活动后过期。我已经搜索了 spring security 但找不到任何东西。

标签: springsessionredirectspring-securityauthorization

解决方案


您需要创建一个服务器端状态,该状态要么为空,要么存储当前声明的访问者的标识符/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 Dissertation中对此进行了更多介绍),但对于您的用例,您需要一种方法来识别多个请求的访问者。会话肯定是实现这一目标的一种非常简单的方法。您至少可以通过一次只创建一个会话来最小化会话使用 - 为持有声明的访问者创建的会话。在这种情况下,您永远不会有超过一个开放会话,并且拥有该会话的访问者就是持有该声明的访问者。

所以在这种情况下,实现将是这样的:

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方法中,以避免两个访问者同时创建声明。


推荐阅读