会话创建和会话销毁事件中的 Spring 安全访问用户详细信息

Posted

技术标签:

【中文标题】会话创建和会话销毁事件中的 Spring 安全访问用户详细信息【英文标题】:Spring security access user Details in session created and session destroyed events 【发布时间】:2015-01-12 12:49:15 【问题描述】:

我正在 Web 应用程序上使用 Spring MVC 4 和 Spring Security 3.1。我有一个要求,我需要在用户登录和注销时更新用户的详细信息。我在这里搜索了很多,找到了解释 Spring 的 HttpSessionListener 和 HttpSessionPublishEvent 使用的答案。我还了解到 SecurityContextHolder.getContext().getAuthentication() 然后获取主体对象在这些侦听器中不起作用。但是有人解释说通过了

      session.getAttribute("SPRING_SECURITY_CONTEXT") 

但是我无法访问

       session.getAttribute("SPRING_SECURITY_CONTEXT")

当用户登录时,我可以获得身份验证和主体对象。在上述两种实现中,每当调用 sessionCreated/sessionDestroyed 事件时,我都会将此属性设为 null。

我的登录页面是使用动作呈现的

      http://localhost:8081/myapp/auth/showLogin 

然后我使用表单登录登录。

 I am using custom UserDetails object as follows :.

 public class SecurityContext 

public static ChatterUserDetails getCurrentUser()
    Object principal = SecurityContextHolder.getContext().getAuthentication().
        getPrincipal();
    if(principal instanceof MyUserDetails)
        return (MyUserDetails) principal;
    
    MyUserDetails anonymousJkWebUserDetails = new  MyUserDetails("anonymous","anonymous",
      new ArrayList<GrantedAuthority>());                                
    anonymousJkWebUserDetails.setAnonymous(true);
    return anonymousJkWebUserDetails;

和security.xml如下(仅相关部分):

  <http use-expressions="true">
          <intercept-url pattern="/auth/showLogin" access="permitAll()"></intercept-url>
        ....
   </http>

   <form-login login-page="/auth/showLogin" always-use-default-target="true"
        default-target-url="/auth/home" authentication-failure-url="/auth/showLogin?error=1"
        login-processing-url="/auth/login" password-parameter="userPassword" 
        username-parameter="userId" />
    <logout logout-success-url="http://$email.link.host" logout-url="/auth/logout" delete-cookies="JSESSIONID" invalidate-session="true"></logout>

【问题讨论】:

我忍不住注意到了这一点,第一个答案看起来很有希望***.com/questions/1629211/… 不.. 我想做的是在用户登录时更新用户信息,并在他注销时再次更新。但是当他登录和注销监听器时如何获取用户ID?我不介意使用任何监听器普通的 sessionlistener 或 spring 的事件监听器 不要为此使用会话侦听器,因为会话也可能因其他原因而创建。创建一个实现 ApplicationListener&lt;AuthenticationSuccessEvent&gt; 的类,这是用户成功登录时从 Spring Security 触发的事件。要捕获注销,让同一类实现LogoutHandler 或侦听HttpSessionDestroyedEvent,后者的优点是还捕获会话失效。还有this issue 用于请求注销事件只是为了这个目的(这在无状态环境中很方便)。 @M.Deinum 谢谢,我就是这么做的,而且效果很好。只是有另一个疑问。触发此 AuthenticationSuccessEvent 时,是否保证已创建/或将创建用户会话。?另外,如果我出于某种原因想在此类事件处理程序中访问会话/上下文怎么办?当我将事件处理程序类声明为另一个 bean 时,我可以将 servlet 上下文/会话直接依赖注入它吗?我已经在这个类中注入了我的一个服务 bean,它可以工作。但不能使用 servletcontext 自动装配? 为什么需要会话,你想要用户(身份验证),这就是你得到的。只要您同步处理事件,您就可以访问会话或您喜欢的任何内容,但通常您希望编写不依赖于此类内容的代码。 【参考方案1】:

在我的例子中,我实现了上面详述的示例,监听 ApplicationListener&lt;InteractiveAuthenticationSuccessEvent&gt; 并注入 HttpSession https://***.com/a/19795352/2213375

【讨论】:

以上是关于会话创建和会话销毁事件中的 Spring 安全访问用户详细信息的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 安全性:请求的 url 创建了不需要的 redis 会话

Spring Security解析八:SessionManagementConfigurer

使用 Spring 安全注册创建会话

使 Spring 安全会话无效

销毁会话,但保留一个变量集

在基于 Spring 的 Web 应用程序中处理会话过期事件