会话创建和会话销毁事件中的 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<AuthenticationSuccessEvent>
的类,这是用户成功登录时从 Spring Security 触发的事件。要捕获注销,让同一类实现LogoutHandler
或侦听HttpSessionDestroyedEvent
,后者的优点是还捕获会话失效。还有this issue 用于请求注销事件只是为了这个目的(这在无状态环境中很方便)。
@M.Deinum 谢谢,我就是这么做的,而且效果很好。只是有另一个疑问。触发此 AuthenticationSuccessEvent 时,是否保证已创建/或将创建用户会话。?另外,如果我出于某种原因想在此类事件处理程序中访问会话/上下文怎么办?当我将事件处理程序类声明为另一个 bean 时,我可以将 servlet 上下文/会话直接依赖注入它吗?我已经在这个类中注入了我的一个服务 bean,它可以工作。但不能使用 servletcontext 自动装配?
为什么需要会话,你想要用户(身份验证),这就是你得到的。只要您同步处理事件,您就可以访问会话或您喜欢的任何内容,但通常您希望编写不依赖于此类内容的代码。
【参考方案1】:
在我的例子中,我实现了上面详述的示例,监听 ApplicationListener<InteractiveAuthenticationSuccessEvent>
并注入 HttpSession
https://***.com/a/19795352/2213375
【讨论】:
以上是关于会话创建和会话销毁事件中的 Spring 安全访问用户详细信息的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 安全性:请求的 url 创建了不需要的 redis 会话