我試圖在我的Spring Boot應用程序中實現「強制註銷」功能(例如,管理員禁用用戶帳戶後)。Spring引導會話管理 - 爲什麼會有兩個sessionRegistry實例?
我按照各種教程中指定的步驟訪問會話註冊表,以便過期用戶的會話(baeldung step 6和verbose version on myyurt;還有related SO)。
然而,註冊SessionRegistryImpl作爲@Bean後,使用調試器時,我看到有在依賴噴射機構2個的不同實例:
一個的SessionRegistry實例在登錄時使用的春季安全並按預期登出並擔任主席和會議。下面的截圖是在登錄後進行的 - 我在registerNewSession()方法中有一個斷點。注意已經登錄用戶的id和地圖。
另一個sessionRegistry實例只被給予我自己的SessionManager類,它需要SessionRegistry作爲依賴並調用getAllPrincipals()。注意ID是不同的,地圖是空的(I稱爲getAllPrincipals()我登錄多次後,把所述第一屏幕截圖)
類其中I註冊的SessionRegistry豆(I除去不必要的代碼只留下我的自定義過濾器,在情況下,它可能是與泉自動配置):
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public static HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Bean
public static SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(myFirstFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(mySecondFilter, FilterSecurityInterceptor.class)
.formLogin() // skipping details
.and()
.x509() // skipping details
.and()
.logout()
.invalidateHttpSession(true)
.permitAll()
.and()
.authorizeRequests() // skipping details
.and()
.sessionManagement()
.invalidSessionUrl("/login")
.enableSessionUrlRewriting(false)
.maximumSessions(-1)
.maxSessionsPreventsLogin(false)
.sessionRegistry(sessionRegistry())
.expiredUrl("/login?expire");
}
}
類,我消費的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
}
}
}
如果有幫助,我擡頭一看豆設置與執行器/豆端點,而這也正是它返回
{
"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-parent 1.5.2.RELEASE,它使用Spring Security 4.2.2.RELEASE。
我不知道它是否相關,但用'@ Bean'註釋的方法不需要是'static'。由於Spring在配置類中使用代理等,這可能是一個探索,但我不確定。也許嘗試刪除靜態關鍵字。 – dunni
我在春天遇到過這樣的問題。你能顯示引用SessionRegistries的對象嗎?在我的情況下,應用程序中有上下文。 – egorlitvinenko
實際上我認爲靜態關鍵字是問題,因爲在你調用'.sessionRegistry(sessionRegistry())'的配置中,它直接調用靜態方法而不是通過Spring代理來獲取應用程序上下文中的bean 。這意味着,爲了您的安全配置,您創建了一個新實例,而不是從應用程序上下文中獲取該bean。 – dunni