springauthenticationspring-securitysession-bean

Spring session bean initialization on event


In my project i need SessionBean to store objects associated with current session. On Session is created and user is authenticated i want to set objects to my bean.

Bean definition:

<bean scope="session" class="org.example.SessionBean">
    <aop:scoped-proxy/>
</bean>

Authentication Listener:

public class SpringAuthenticationListener implements ApplicationListener<ApplicationEvent> {

private LogService logService;

private UserService userService;

@Autowired
private SessionBean sessionBean;

public SpringAuthenticationListener(LogService logService, UserService userService) {
    this.logService = logService;
    this.userService = userService;
}

@Override
public void onApplicationEvent(ApplicationEvent e) {
    LogEvent logEvent = new LogEvent();

    if (e instanceof AuthenticationSuccessEvent) {
        AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) e;
        UserDetails userDetails = (UserDetails) event.getAuthentication().getPrincipal();

        User loggedUser = userService.getUser( userDetails.getUsername() );
        sessionBean.setLoggedUser(loggedUser);
    } 
}

}

But, problem is that i can't getting an instance of current SessionBean instance. That's my error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.org.example.SessionBean#0': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

How should i do this ? What event or listener will let me initialize SessionBean with current user.


Solution

  • Spring Security operates using a Filter filters are executed before any Servlet and as such also before the DispatcherServlet. To be able to use request or session scoped beans a RequestContext is needed. This is normally prepared by the DispatcherServlet. When wanting to use scoped beans outside of the DispatcherServlet you need to do some additional setup. As also stated by the exception:

    use RequestContextListener or RequestContextFilter to expose the current request.

    To fix add a RequestContextListener or RequestContextFilter to your web.xml. When using the latter make sure it is executed before the springSecurityFilterChain else it won't take effect. The listener is always executed before any filter.