Announcement Announcement Module
Collapse
No announcement yet.
Make SpringSecurity actually logout a user on ChannelSet.logout() Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Make SpringSecurity actually logout a user on ChannelSet.logout()

    Hi,

    I am struggling with the following problem:
    I have created a component that is called by spring security whenever a user does a Login/Login Failure/Logout and sends an Event to the application backend. This works fine as long as I configure form-based login and logout using "/j_spring_security_logout". When using flex' ChannelSet.login my component is called correctly.

    Unfortunately a ChannelSet.logout() doesn't trigger a real logout as I am still logged in in Spring Security, but simply can't use the ChannelSet anymore. I would really like to avoid having to redirect the browser to "j_spring_security_logout" and to reload the Flash application in order to make this work.

    Any help greatly appreciated :-)

    And by the way ... merry Christmas :-)

  • #2
    Found the Reason ... but how to fix?

    Ok ... I really hate replying to my own posts ... especially after having posted after quite some time of investigation. Shortly after my first post, I noticed that the org.springframework.flex.security.SpringSecurityLo ginCommand performs a logout by calling: SecurityContextHolder.clearContext()
    and that the org.springframework.security.ui.logout.LogoutFilte r detects a logout by checking, if the uri of the current request is "/j_spring_security_logout" (or what is configured as logout url) so it seems that I only thought I was not logged out and the reason that my event dispatcher wasn't called was that LogoutFilter was not able to detect the logout the way the SpringSecurityLoginCommand performs it.

    Any suggestions on how to fix this? I think the LogoutFilter is a pretty basic functionality of SpringSecurity, so I think we should make this work.

    Comment


    • #3
      The only way that I was able to tell the server that the user was really logged out was to redirect. You are right the ChannelSet.logout() only closes the channel but doesn't kill the session on the server.

      You can set it up to redirect you to the flex app if you want. Though I am using a jsp login for separation as an extra security measure.

      You can really see this if you set up non-concurrent users, meaning you can only log in to one app at a time and must log out to log in some where else. If you don't redirect to "/j_spring_security_logout" then the server thinks that you are still logged in while the channel is closed. This means that you will never log in again.

      Also there is a updated security example in the TestDrive example in the new SBI 1.0.1.

      I am not sure if this answers your question or I am talking about something else.

      Joshua

      Comment


      • #4
        Well I guess I'll start implmenting my own custom LogoutFilter in order to boradcast the Logout events as I think checking on "j_spring_security_logout" is not really the best thing to do and while I'm at it, I'll continue debugging throug the code to see how Spring security works here. I guess there will be more need to debug, but I really want to avoid the redirect.

        Comment


        • #5
          Custom LogoutFilter

          Hi,

          as I mentioned, the LogoutFilter as it is implemented in Sprin Secutity will not detect a logout by anything else than a url. So I imeplemented my own one that is able to detect the logout command issued by ChannelSet.logout(). Using this implementation my event-dispatcher gets called as expected.

          Code:
          package de.cware.cweb.webapp.security;
          
          import org.springframework.security.Authentication;
          import org.springframework.security.context.SecurityContextHolder;
          import org.springframework.security.ui.FilterChainOrder;
          import org.springframework.security.ui.SpringSecurityFilter;
          import org.springframework.security.ui.logout.LogoutHandler;
          import org.springframework.util.Assert;
          
          import javax.servlet.FilterChain;
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;
          
          /**
           * Logs a principal out.
           * <p>
           * Polls a series of {@link org.springframework.security.ui.logout.LogoutHandler}s. The handlers should be specified in the order they are required.
           * Generally you will want to call logout handlers <code>TokenBasedRememberMeServices</code> and
           * <code>SecurityContextLogoutHandler</code> (in that order).
           * </p>
           * This version principally does the same as the original LogoutFilter but it detects a logout
           * not by analysing the request-url but by inspecting the ContextHolder content. It allows detection
           * of system-logouts performed by setting the ContextHolder content to null.
           *
           * @author Christofer Dutz
           */
          public class LogoutFilter extends SpringSecurityFilter {
          
              //~ Instance fields ================================================================================================
          
              private LogoutHandler[] handlers;
          
              //~ Constructors ===================================================================================================
          
              public LogoutFilter(LogoutHandler[] handlers) {
                  Assert.notEmpty(handlers, "LogoutHandlers are required");
                  this.handlers = handlers;
              }
          
              //~ Methods ========================================================================================================
          
              public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException,
                      ServletException {
          
                  final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
                  final boolean wasLoggedOut = auth == null;
          
                  chain.doFilter(request, response);
          
                  final boolean isLoggedOut = SecurityContextHolder.getContext().getAuthentication() == null;
          
                  if(isLoggedOut && !wasLoggedOut) {
                      if (logger.isDebugEnabled()) {
                          logger.debug("Logging out user '" + auth + "' and redirecting to logout page");
                      }
          
                      for (int i = 0; i < handlers.length; i++) {
                          handlers[i].logout(request, response, auth);
                      }
                  }
              }
          
              public int getOrder() {
                  return FilterChainOrder.LOGOUT_FILTER;
              }
          }

          Comment


          • #6
            It sounds like there is definitely some room for improvement here. We had gone through a few different options with how to handle logout, but ultimately settled on the simplest one in hopes that further requirements might emerge as people actually use it (as they now have ).

            What the SpringSecurityLoginCommand does at the moment is essentially equivalent to what the standard SecurityContextLogoutHandler does, except that we don't do any of the optional session invalidation. (I believe we experimented with a session invalidation option at one point, but it was difficult to decide how that should work in conjunction with the FlexSession, so we left it out.)

            It sounds like the main thing you guys are missing from the typical LogoutFilter process is the session invalidation, is that right?

            If that's the case, we can explore adding such an option. Maybe what we really should be doing is getting ahold of the LogoutHandlers and invoking those, which is a little more difficult but could probably be done.

            Comment


            • #7
              Well what I needed to do in my case was to make spring security call my LogoutHandlers when logging out by the ChannelSet.logout() command. I have changed my Spring Security configuration to use my custom LogoutCommand and I am currently very sattisfied using this approach as it solves all my problems ;-)

              Comment


              • #8
                Chris - I also have this issue. Could you post the xml config for the LogoutFilter. I'd like to use this workaround until the 1.5 release comes out. Thanks in advance as I also do not want to have to redirect the user to another page!

                Comment


                • #9
                  Config

                  Sure ... here you go ... hope it helps ... seems that it works so good for me that I completely forgot what I did then ;-)

                  Code:
                     <!-- configure the logout filter. This is used to be able to react on logout event -->
                      <bean id="logoutFilter" class="de.cware.cweb.webapp.security.LogoutFilter">
                          <security:custom-filter position="LOGOUT_FILTER"/>
                          <constructor-arg>
                              <list>
                                  <ref bean="securityEventDispatcher"/>
                                  <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler"/>
                              </list>
                          </constructor-arg>
                      </bean>

                  Comment


                  • #10
                    Thank you so much for your quick response! I am using the new Spring 3, and while I am trying to implement your workaround I found out that SpringSecurityFilter is no longer available. I could extend GenericFilterBean but I think there is a LogoutFilter available in spring 3.

                    I am doing more research and trying to find out if I can accomplish this with a custom LogoutSuccessHandler with standard LogoutFilter. Though the LogoutFilter is very similar to yours, so I'm wondering if I should just override the new one. Thoughts?

                    Comment

                    Working...
                    X