Spring Security多个登录用户失败

时间:2016-11-18 13:30:26

标签: java spring hibernate spring-mvc spring-security

我正在使用Spring,Spring Security和Hibernate制作一个基本的Tic tac toe项目。应用程序可以为数据库中的每个已登录用户保存游戏,并允许随时加载它。这不是一个问题,但它出现在多线程上。当我在单个浏览器窗口中运行单个应用程序时,一切正常。但当我打开另一个窗口时,两个玩家正在玩同一个游戏。

我知道这可能是由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);
}

当多个用户登录时,该metod仅打印其中一个用户的名称。我不知道为什么。以下是我的安全配置和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");
}

可能有什么问题?

1 个答案:

答案 0 :(得分:3)

SecurityContextHolder使您可以访问与当前线程关联的安全上下文,从而只访问当前用户 - 其请求触发对{的调用的用户{1}},所以它的行为完全符合它应该的方式。

另一方面,如果您想要所有活动会话(即所有登录用户),您应该注入getAuthentication()并在其上调用SessionRegistry

详情已经提供here