1

我有一个使用 Spring 3.1.1 和 Spring Security 3.1.0 的 Web 应用程序。我实现了一个 ApplicationListener,它检查 SessionDestroyedEvent(s) 并记录用户名和其他数据。但是,getSecurityContexts() 总是返回一个空集合。我正在针对 LDAP 服务器进行身份验证。我还检查了 getSource() 方法,它返回包含 Principal 信息的会话数据。但是,这些对象是不同的容器特定实现,并且没有我可以使用的接口/抽象类。我的问题是这是否是 SpringSecurity 中的一个错误,或者我可以做一些额外的配置吗?

以下是一些相关代码:

@Service
public class ApplicationSecurityListener implements ApplicationListener<ApplicationEvent>{

@Override
  public void onApplicationEvent(ApplicationEvent event)
  {
           else if ( event instanceof SessionDestroyedEvent )
    {
        SessionDestroyedEvent sessinEvent = ( SessionDestroyedEvent ) event;
        //System.out.println ( "SessionDestroyedEvent:" + sessinEvent.getId() );
        //load session if it is not empty
        if(sessinEvent.getSecurityContexts() != null && !sessinEvent.getSecurityContexts().isEmpty())
        {
            ...
            }}}}
4

1 回答 1

2

这是 3.1.0 中的一个错误,将作为 3.1.1 的一部分发布(参见SEC-1870)。在 3.1.1 发布之前,您可以通过手动获取 onApplicationEvent 中的 SecurityContext 来解决此问题。使用前面提到的 JIRA 中的变更集作为指南,您会想出如下内容:

public void onApplicationEvent(ApplicationEvent event) {
    if(event instanceof SessionDestroyedEvent) {
        SessionDestroyedEvent sdEvent = (SessionDestroyedEvent) event;    
        HttpSession session = sdEvent.getSession();    
        Enumeration<String> attributes = session.getAttributeNames();    
        ArrayList<SecurityContext> contexts = new ArrayList<SecurityContext>();

        while(attributes.hasMoreElements()) {
            String attributeName = attributes.nextElement();
            Object attributeValue = session.getAttribute(attributeName);
            if (attributeValue instanceof SecurityContext) {
                contexts.add((SecurityContext) attributeValue);
            }
        }
        /* ... do things with the contexts (may be empty) ...*/
    }

    /* ... handle other conditions ... */

}

如果您知道只有一个 SecurityContext 并且您没有更改存储 SecurityContext 的属性名称(典型),您也可以使用以下方法获取它:

public void onApplicationEvent(ApplicationEvent event) {
    if(event instanceof SessionDestroyedEvent) {
        SessionDestroyedEvent sdEvent = (SessionDestroyedEvent) event;    
        HttpSession session = sdEvent.getSession();
        String attrName = HttpSessionSecurityContextRepository
            .SPRING_SECURITY_CONTEXT_KEY;
        SecurityContext context = session.getAttribute(attrName);

        /* ... do things with the context (may be null) ...*/
    }

    /* ... handle other conditions ... */

}
于 2012-06-27T02:27:38.410 回答