2016-11-18 126 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