java 我可以使用 Spring Security 管理多个浏览器选项卡吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6128134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:27:41  来源:igfitidea点击:

Can I manage multiple browser tabs with Spring Security?

javajsfspring-security

提问by caarlos0

I wonder if, with Spring Security, I can validate the user sessions, allowing only one browser tab open. Is it possible?

我想知道使用 Spring Security 是否可以验证用户会话,只允许打开一个浏览器选项卡。是否可以?

I would also like to know if I can do it, when the user closes the tab and open it again before the end of his session SessionFilter it from direct application, without going to the login screen.

我还想知道我是否可以做到,当用户关闭选项卡并在他的会话结束之前再次打开它时,直接应用程序 SessionFilter 它,而无需进入登录屏幕。

I'm using JSF 1.2, RichFaces 3.3.3, Hibernate and co ...

我正在使用 JSF 1.2、RichFaces 3.3.3、Hibernate 和 co ...

Detail: I know the spring security, I'm just researching it.

详细信息:我知道弹簧安全性,我只是在研究它。

Now thanks and excuse me for my bad English.

现在感谢并原谅我的英语不好。

See ya!

拜拜!

采纳答案by BobG

No. Spring Security cannot tell if the request was from the original tab or from a new tab - that information is strictly client-side. From http://static.springsource.org/spring-security/site/faq.html:

不。Spring Security 无法判断请求是来自原始选项卡还是来自新选项卡 - 该信息严格是客户端。从http://static.springsource.org/spring-security/site/faq.html

2.1.

I'm using Spring Security's concurrent session control to prevent users from logging in more than once at a time. When I open another browser window after logging in, it doesn't stop me from logging in again. Why can I log in more than once?

Browsers generally maintain a single session per browser instance. You cannot have two separate sessions at once. So if you log in again in another window or tab you are just reauthenticating in the same session. The server doesn't know anything about tabs, windows or browser instances. All it sees are HTTP requests and it ties those to a particular session according to the value of the the JSESSIONID cookie that they contain. When a user authenticates during a session, Spring Security's concurrent session control checks the number of other authenticated sessions that they have. If they are already authenticated with the same session, then re-authenticating will have no effect.

2.1.

我正在使用 Spring Security 的并发会话控制来防止用户一次登录多次。当我登录后打开另一个浏览器窗口时,它不会阻止我再次登录。为什么我可以登录多次?

浏览器通常为每个浏览器实例维护一个会话。您不能同时进行两个单独的会话。因此,如果您在另一个窗口或选项卡中再次登录,您只是在同一个会话中重新进行身份验证。服务器对选项卡、窗口或浏览器实例一无所知。它看到的只是 HTTP 请求,并根据它们包含的 JSESSIONID cookie 的值将这些请求与特定会话联系起来。当用户在会话期间进行身份验证时,Spring Security 的并发会话控制会检查他们拥有的其他经过身份验证的会话的数量。如果它们已经通过同一会话进行了身份验证,则重新进行身份验证将无效。

回答by Jigar Parekh

I have recently implemented a solution to multiple tabs/windows using Spring Security. For successful login I use `LoginSucessHandler`` and set an unique window name in session. On the main template page I have setup a window name and on each page load verify window name with session's window name, if it is not the same then redirect to the error page.

我最近使用 Spring Security 为多个选项卡/窗口实现了一个解决方案。为了成功登录,我使用“LoginSucessHandler”并在会话中设置一个唯一的窗口名称。在主模板页面上,我设置了一个窗口名称,并在每个页面加载时使用会话的窗口名称验证窗口名称,如果不同,则重定向到错误页面。

Below are configurations and code:

下面是配置和代码:

@Service
public class LoginSucessHandler extends
        SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
            throws ServletException, IOException {
        User user = (User) authentication.getPrincipal();
        String windowName = user.getUsername() + new Date().getTime();
        HttpSession session = request.getSession();
        session.setAttribute("windowName", windowName);
        session.setAttribute("windowNameToSet", windowName);
        super.onAuthenticationSuccess(request, response, authentication);
    }

}

Main template or header page:

主模板或标题页:

<script>
  <%if (session.getAttribute("windowNameToSet") != null) {
        out.write("window.name = '"
            + session.getAttribute("windowNameToSet") + "';");
        session.removeAttribute("windowNameToSet");
  }%>
  if (window.name != "<%=session.getAttribute("windowName")%>") {
        window.location = "<%=request.getContextPath()%>/forms/multiwindowerror.jsp";
  }
</script>

For security context:

对于安全上下文:

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/login.hst**" access="anonymous or authenticated" />
    <intercept-url pattern="/**/*.hst" access="authenticated" />
    <form-login login-page="/login.hst"
        authentication-failure-url="/login.hst?error=true"
        authentication-success-handler-ref="loginSucessHandler" />
    <logout invalidate-session="true" logout-success-url="/home.hst"
        logout-url="/logout.hst" />
    <remember-me key="jbcp" authentication-success-handler-ref="loginSucessHandler"/>
</http>

Just make sure that on login.jsp above JavaScript is not included.

只要确保上面的 login.jsp 不包含 JavaScript。

回答by user2150136

I figured out an easier way to accomplish the same thing. If you're already extending SimpleUrlAuthenticationSuccessHandler, similar to @Jagar, create an arraylist of logged in users, add the user to it, and add that to the session. Then each time you log in, check if the session exists and if that user is in the session arraylist attribute. If it is, then fail, if it isn't, allow the login.

我想出了一个更简单的方法来完成同样的事情。如果您已经扩展了SimpleUrlAuthenticationSuccessHandler,类似于@Jagar,请创建一个已登录用户的数组列表,将用户添加到其中,然后将其添加到会话中。然后每次登录时,检查会话是否存在以及该用户是否在会话数组列表属性中。如果是,则失败,如果不是,则允许登录。

That way you can have multiple users logged in with the same browser, but not the same user. That also prevents the possibility of incorrectly overwriting the windowName attribute.

这样你就可以让多个用户使用同一个浏览器登录,但不是同一个用户。这也防止了错误覆盖 windowName 属性的可能性。