从HttpSessionListener春季运行SamlLogoutHandler

时间:2018-10-30 17:31:02

标签: java spring saml httpsession

只要我的HttpSession过期,我就需要使SAML(okta)会话无效。为此,我创建了HttpSessionListener,并且其destroy方法在会话destroy上成功执行,因此可以在此处插入我的代码:

@Bean
    public HttpSessionListener httpSessionListener() {
        return new HttpSessionListener() {
            @Override
            public void sessionCreated(HttpSessionEvent se) {
                System.out.println("Session Created with session id+" + se.getSession().getId());
            }

            @Override
            public void sessionDestroyed(HttpSessionEvent se) {
                System.out.println("Session Destroyed, Session id:" + se.getSession().getId());
            }
        };
    }

我发现Spring允许使用其自己的类使SAML会话无效,因此我将一些代码复制到新类中,如下所示:

public class SamlLogoutHandler extends SimpleUrlLogoutSuccessHandler {
    private static final String LOGOUT_PARAMETER = "local";

    private SingleLogoutProfile profile;

    private SAMLContextProvider contextProvider;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                Authentication authentication) throws IOException, ServletException {
        try {
            if (authentication != null && isGlobalLogout(request, authentication)) {

                Assert.isInstanceOf(SAMLCredential.class, authentication.getCredentials(),
                    "Authentication object doesn't contain SAML credential, cannot perform global logout");

                // Terminate the session first
                HttpSession session = request.getSession(false);
                SecurityContextHolder.clearContext();
                if (session != null) {
                    session.invalidate();
                }

                // Notify session participants using SAML Single Logout profile
                SAMLCredential credential = (SAMLCredential) authentication.getCredentials();
                request.setAttribute(SAMLConstants.LOCAL_ENTITY_ID, credential.getLocalEntityID());
                request.setAttribute(SAMLConstants.PEER_ENTITY_ID, credential.getRemoteEntityID());
                SAMLMessageContext context = contextProvider.getLocalAndPeerEntity(request, response);
                profile.sendLogoutRequest(context, credential);
            }
        } catch (SAMLException e) {
            logger.debug("Error initializing global logout", e);
            throw new ServletException("Error initializing global logout", e);
        } catch (MetadataProviderException e) {
            logger.debug("Error processing metadata", e);
            throw new ServletException("Error processing metadata", e);
        } catch (MessageEncodingException e) {
            logger.debug("Error encoding outgoing message", e);
            throw new ServletException("Error encoding outgoing message", e);
        }

        super.onLogoutSuccess(request, response, authentication);
    }

    private boolean isGlobalLogout(HttpServletRequest request, Authentication auth) {
        String localLogout = request.getParameter(LOGOUT_PARAMETER);
        return (localLogout == null || !"true".equals(localLogout.toLowerCase().trim()))
            && (auth.getCredentials() instanceof SAMLCredential);
    }

    public void setProfile(SingleLogoutProfile profile) {
        this.profile = profile;
    }

    public void setContextProvider(SAMLContextProvider contextProvider) {
        this.contextProvider = contextProvider;
    }
}

问题是:如何从侦听器运行onLogoutSuccess方法?还是我可以更轻松地做到这一点?

0 个答案:

没有答案