springboot spring session redis spring security 相同用戶單個session的解決方案

首先還是吐槽,百度了兩天,嘗試了十多種方案,各種重寫,無效。。。。。最後,還是在官網找到解決方案。

哎。。。已經很多次了。官網。官網。官網。。以後要多看官網。

 

還是描述下需求吧。很簡單,相同的用戶登錄時,只能保留最後一個session。防止多處登錄。也不算是單點。

在開始貼代碼之前,各位看官一定要注意條件

springboot+spring session redis+spring security ,使用java config方式。

可能不使用spring session redis 或者 spring security的情況,不會出現我的問題,因爲不涉及redis session的控制。

 

一般情況下,如果使用spring自帶的內存管理方式,非常簡單就可以實現(沒有嘗試,看百度應該問題不大)

springsecurity配置中

@Override
	protected void configure(HttpSecurity http) throws Exception {
....
http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false).expiredUrl("/login?expired");
		
	}

而使用了spring session  redis,則在spring security對登陸session控制的默認實現類SessionRegistryImpl中判斷session時,無法獲取正確的獲取session。特別是重啓應用後,基於內存的SessionRegistryImpl就會丟失session,而redis中的還存在。登陸成功的用戶還能操作,而SessionRegistryImpl中,則沒有任何session了。

所以,解決方案是,在springsecurity配置中,註冊spring session redis 的sessionregistry。代碼如下(20191024修改):

@Configuration
@Import({ SessionRedisConfig.class })
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啓security註解
public class WebSecurityConfig<S extends Session> extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private FindByIndexNameSessionRepository<S> sessionRepository;
	
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {

		// 允許所有用戶訪問"/"和"/register"
		http.authorizeRequests().antMatchers("/", "/public/**","/static/**", "/login").permitAll()
				.antMatchers("/admin/**").hasRole("ADMIN")
				// 其他地址的訪問均需驗證權限
				.anyRequest().authenticated()// .hasRole("USER")
				.and().formLogin()
				// 指定登錄頁是"/login"
				.loginPage("/login")
				// .failureUrl("/login?error=true")
				.defaultSuccessUrl("/main").permitAll()
				.and().headers().frameOptions().disable().and().logout()
				.logoutUrl("/logout").logoutSuccessUrl("/").permitAll();
		http.exceptionHandling().accessDeniedPage("/403")
			.and().csrf().disable();
		//not create new session
		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
		//ori session user
		http.sessionManagement().sessionFixation().none();
		http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false).expiredUrl("/login")
		.sessionRegistry(sessionRegistry());
		//http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
	}
	
	@Bean
    SpringSessionBackedSessionRegistry<S> sessionRegistry() {
            return new SpringSessionBackedSessionRegistry<S>(sessionRepository);
    }
	
	

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章