2016-11-18 123 views
0

我正在用Spring,Spring Security和Hibernate製作一個基本的井字遊戲項目。應用程序可以將每個記錄的用戶的遊戲保存在數據庫中,並允許在需要時加載它。這不是問題,但它涉及到多線程。當我在單個瀏覽器窗口中運行單個應用程序時,一切正常。但是當我打開另一個窗口時,兩個玩家正在玩同一個遊戲。Spring Security多個登錄用戶失敗

我知道它可能是由Spring創建的bean單例造成的,但我相信它不是。要檢查當前登錄的用戶,我做了一個方法來從SecurityContextHolder中

private User getUserFromSpringContext() { 
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
    String name = authentication.getName(); 
    System.out.println("Currently logged users = " + name); 
    return userService.findUserByUsername(name); 
} 

當多個用戶登錄,但其中只有一個那梅託德版畫名得到他。我不知道爲什麼。下面是一些重要的代碼行我的安全配置,併爲userDetails類:

安全配置:

@Autowired 
UserDetailsService userDetailsService; 

@Autowired 
public void configureGlobalSecurity(AuthenticationManagerBuilder builder) throws Exception { 
    builder.userDetailsService(userDetailsService); 
    builder.authenticationProvider(authenticationProvider()); 
} 

@Bean 
public DaoAuthenticationProvider authenticationProvider() { 
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider(); 
    auth.setUserDetailsService(userDetailsService); 
    return auth; 
} 

自定義用戶的詳細信息服務

@Autowired 
private UserService userService; 

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
    User user = userService.findUserByUsername(username); 
    if (user == null) { 
     throw new UsernameNotFoundException("Username not found"); 
    } 
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), true, true, true, true, getAuthoriries(user)); 
} 

public void setUserService(UserService userService) { 
    this.userService = userService; 
} 

private List<GrantedAuthority> getAuthoriries(User user) { 
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    authorities.add(new SimpleGrantedAuthority(user.getRole().getRole())); 
    return authorities; 
} 

有誰知道這個問題的原因是什麼?

在測試過程中,我想出了另一個問題。當我單擊註銷時,所有用戶都註銷。我在這裏發佈我的Spring Security配置的其餘部分。

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests() 
      .antMatchers("/start", "/", "/login", "/registry","/success","/new").permitAll() 
      .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") 
      .antMatchers("/**").access("hasAnyRole('ROLE_USER','ROLE_ADMIN')") 
      .and().formLogin().loginPage("/login").defaultSuccessUrl("/user") 
      .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) 
      .and().csrf() 
      .and().exceptionHandling().accessDeniedPage("/access_denied"); 
} 

什麼可以是問題?

+0

假設它按我認爲的方式工作,您是否斷言(但是)當用戶登錄時,它們的條目是在您的數據庫中創建的?也許它只適用於第一個用戶? –

+0

我編輯後,因爲我發現了另一個問題。 –

+0

定義打開一個新窗口?如果你是從你現有的不是新瀏覽器的瀏覽器中按CTRL + T或CTRL + N。會話狀態,緩存和cookie將被複制。實際上,您並不是在玩多個玩家,而是在多個瀏覽器窗口中使用單個用戶。我會說它應該像它應該的那樣工作,而你只是以錯誤的方式進行測試。 –

回答

3

SecurityContextHolder,您可以訪問與當前線程相關的安全上下文,因此只有當前用戶 - 其請求觸發調用getAuthentication()的一個,所以它的表現它應該完全相同的方式。

另一方面,如果你想要所有的活動會話(即所有登錄用戶),你應該注入SessionRegistry並呼籲sessionRegistry.getAllPrincipals()就可以了。

詳情已經給出here