Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring启动会话管理-为什么有两个sessionRegistry实例?_Java_Spring_Spring Mvc_Spring Boot_Spring Security - Fatal编程技术网

Java Spring启动会话管理-为什么有两个sessionRegistry实例?

Java Spring启动会话管理-为什么有两个sessionRegistry实例?,java,spring,spring-mvc,spring-boot,spring-security,Java,Spring,Spring Mvc,Spring Boot,Spring Security,我试图在我的Spring Boot应用程序中实现“强制注销”功能(例如,管理员禁用用户帐户后) 我按照各种教程中指定的步骤访问会话注册表,以便使用户的会话过期(还有) 但是,在将SessionRegistryImpl注册为@Bean之后,在使用调试器时,我看到依赖项注入机制中有两个不同的实例: Spring Security在登录和注销时使用一个sessionRegistry实例,并按预期保存主体和会话。下面的屏幕截图是在登录后拍摄的-我在registerNewSession()方法中有一个断

我试图在我的Spring Boot应用程序中实现“强制注销”功能(例如,管理员禁用用户帐户后)

我按照各种教程中指定的步骤访问会话注册表,以便使用户的会话过期(还有)

但是,在将SessionRegistryImpl注册为@Bean之后,在使用调试器时,我看到依赖项注入机制中有两个不同的实例:

  • Spring Security在登录和注销时使用一个sessionRegistry实例,并按预期保存主体和会话。下面的屏幕截图是在登录后拍摄的-我在registerNewSession()方法中有一个断点。请注意id和已登录用户的地图。

  • 另一个sessionRegistry实例只提供给我自己的SessionManager类,它需要sessionRegistry作为依赖项并调用GetAllPrinciples()。注意,id是不同的,映射是空的(我在多次登录并拍摄第一个屏幕截图后调用了getAllPrincipals()

类注册sessionRegistry bean(我删除了不必要的代码,只留下了自定义过滤器,以防它可能与Springs自动配置有关):

类,其中我使用sessionRegistry依赖项:

@Component
class DefaultSessionManager implements SessionManager {    
    private final SessionRegistry sessionRegistry;

    @Autowired public DefaultSessionManager(SessionRegistry sessionRegistry) {
        this.sessionRegistry = sessionRegistry;
    }

    public void expireUserSessions(String username) {
        for (Object principal : sessionRegistry.getAllPrincipals()) {
            // do stuff, but won't enter because the list is empty
        }
    }
}
如果有帮助的话,我会使用exactor/beans端点查找bean设置,这就是它返回的结果

        {
            "bean": "defaultSessionManager",
            "aliases":
            [
            ],
            "scope": "singleton",
            "type": "com.foo.bar.DefaultSessionManager",
            "resource": // file path
            "dependencies":
            [
                "sessionRegistry"
            ]
        },

        {
            "bean": "httpSessionEventPublisher",
            "aliases":
            [
            ],
            "scope": "singleton",
            "type": "org.springframework.security.web.session.HttpSessionEventPublisher",
            "resource": "class path resource [com/foo/bar/SecurityConfig.class]",
            "dependencies":
            [
            ]
        },
        {
            "bean": "sessionRegistry",
            "aliases":
            [
            ],
            "scope": "singleton",
            "type": "org.springframework.security.core.session.SessionRegistryImpl",
            "resource": "class path resource [com/foo/bar/SecurityConfig.class]",
            "dependencies":
            [
            ]
        },
如果所有实例都声明为单实例,那么DI系统中怎么会有两个不同的实例? 你有什么关于什么可能是错误的提示吗


我使用的是spring boot starter父级1.5.2.RELEASE,它使用spring Security 4.2.2.RELEASE。

问题是
@Bean
注释方法上的静态关键字。在您调用

.sessionRegistry(sessionRegistry())

它直接调用静态方法,而不是通过Spring代理从应用程序上下文获取bean。这意味着,对于您的安全配置,您将创建一个新实例,而不是从应用程序上下文获取bean。对于非静态方法,Spring会截取相同调用中的直接方法调用,然后检查bean是否已经存在于应用程序上下文中,如果存在,则返回bean。

我不知道它是否相关,但是使用
@bean
注释的方法不需要是
静态的。由于Spring在配置类中使用代理等,这可能是个问题,但我不确定。也许可以尝试删除静态关键字。我在春天遇到了这样的问题。可以显示引用会话注册表的对象吗?在我的例子中,应用程序中有上下文。实际上,我认为静态关键字是问题所在,因为在您调用
.sessionRegistry(sessionRegistry())
的配置中,它会直接调用静态方法,而不是通过Spring代理从应用程序上下文获取bean。这意味着,对于您的安全配置,您将创建一个新实例,而不是从应用程序上下文获取bean。谢谢,@dunni,就是这样。我移除了静电场,它现在可以工作了。。。我还没想到。如果你愿意,请将此作为答案发布,我会接受。干杯谢谢,在这一点上,他们不是很有帮助。但我会记住未来。这里发生了很多神奇的事情。一个普遍的经验法则(不是官方的,只是从我这边):静态和弹簧通常不能很好地结合在一起。
.sessionRegistry(sessionRegistry())