java - 如何使用Spring正确获取用户列表?

标签 java spring spring-boot spring-security spring-messaging

我想获取所有经过身份验证的用户的列表。
我学习了基本的 spring-security example来自 Spring 官方网站。

正如其他相关问题( 51992610 )中所建议的那样,我将 DefaultSimpUserRegistry 注入(inject)到代码中。 尽管如此,该列表还是空的。

@Configuration
public class UsersConfig {
    final private SimpUserRegistry userRegistry = new DefaultSimpUserRegistry();
    
    @Bean
    @Primary
    public SimpUserRegistry userRegistry() {
        return userRegistry;
    }
}
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                            .antMatchers("/", "/home").permitAll()
                            .anyRequest().authenticated()
                            .and()
                    .formLogin()
                            .loginPage("/login")
                            .permitAll()
                            .and()
                    .logout()
                            .permitAll();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
            UserDetails user =
                     User.withDefaultPasswordEncoder()
                            .username("u")
                            .password("11")
                            .roles("USER")
                            .build();

            return new InMemoryUserDetailsManager(user);
    }
}
@RestController
public class WebSocketController {

    @Autowired
    private final SimpUserRegistry simpUserRegistry;

    public WebSocketController(SimpUserRegistry simpUserRegistry) {
        this.simpUserRegistry = simpUserRegistry;
    }

    @GetMapping("/users")
    public String connectedEquipments() {
        
        return this.simpUserRegistry
                .getUsers()
                .stream()
                .map(SimpUser::getName)
                .collect(Collectors.toList()).toString();
    }
}

构建 jar,本地启动,登录,输入 http://localhost:8080/users。结果:

[]

完整的代码可以取自 Spring 站点。 SimpUserRegistry 上的主题非常罕见,我找不到完整的示例。类似的帖子尚未得到答复( 4880478058925128 )。

抱歉,我是 Spring 新手,SimpUserRegistry 是使用 Spring 列出用户的正确方法吗?如果可以的话,该如何正确使用呢?谢谢。

最佳答案

在您的问题中,您正在尝试一些事情:

  1. 您正在使用允许的用户列表(在您的例子中,用户名为 u)设置 InMemoryUserDetailsManager
  2. 您正在使用 SimpUserRegistry 通过 Spring 消息传递(例如使用 WebSockets)获取所有已连接用户的列表。

如果您只是想获取所有用户的列表,并且没有使用 WebSocket,那么第二种方法将不起作用

如果您尝试获取存储在 InMemoryUserDetailsManager 中的所有用户的列表,那么答案是不可能获取该列表。 InMemoryUserDetailsManager 使用内存中的Map 来存储所有用户,并且它不会公开该列表。

如果您确实想要这样的列表,则必须创建一个自定义内存中UserDetailsS​​ervice,例如:

@Service
public class ListingInMemoryUserDetailsService implements UserDetailsService {
    private final Map<String, InMemoryUser> users;

    public ListingInMemoryUserDetailsService() {
        this.users = new HashMap<>();
    }

    public ListingInMemoryUserDetailsService(UserDetails... userDetails) {
        this.users = stream(userDetails)
            .collect(Collectors.toMap(UserDetails::getUsername, InMemoryUser::new));
    }

    public Collection<String> getUsernames() {
        return users
            .values()
            .stream()
            .map(InMemoryUser::getUsername)
            .collect(toList());
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return Optional
            .ofNullable(users.get(username))
            .orElseThrow(() -> new UsernameNotFoundException("User does not exist"));
    }
}

在此示例中,InMemoryUserUserDetails 接口(interface)的实现。当您创建这样的自定义实现时,您必须使用 Spring Security 配置它:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder);
}
<小时/>

或者,如果您有兴趣检索所有已创建 session 的列表,还有更好的方法。首先,您必须创建一个 SessionRegistry bean:

@Bean
public SessionRegistry sessionRegistry() {
    return new SessionRegistryImpl();
}

然后,您必须配置 Spring Security 来设置 session ,并使用 SessionRegistry 来执行此操作:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/", "/home").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login").permitAll()
            .and()
        .logout().permitAll()
        // Add something like this:
        .sessionManagement()
            .maximumSessions(1)
            .sessionRegistry(sessionRegistry);
}

之后,您可以 Autowiring SessionRegistry,并使用getAllPrincipals()方法:

@GetMapping("/users")
public Collection<String> findUsers() {
    return sessionRegistry
        .getAllPrincipals()
        .stream()
        .map(this::getUsername)
        .flatMap(Optional::stream)
        .collect(toList());
}

private Optional<String> getUsername(Object principal) {
    if (principal instanceof UserDetails) {
        return Optional.ofNullable(((UserDetails) principal).getUsername());
    } else {
        return Optional.empty();
    }
}

这将列出在应用程序中登录并进行 session 的所有用户的用户名。这还包括过期的 session ,因此您可能还需要过滤这些 session 。

关于java - 如何使用Spring正确获取用户列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59195672/

相关文章:

java - adapter.getItem() 将返回什么?

java - 如何将 parseInt 用于 double ?

java - Spring - @Named 和 @Component 之间的区别

java - 自定义错误页面未捕获 tomcat 中引发的异常

java - EHCache中的EH代表什么?

sql - 有没有非常轻量级的数据库java库?

spring - Gradle:不能从Maven存储库解析Spring依赖项

java - IntelliJ + Spring Web MVC

oracle11g - Spring Boot : How to set retry attempts for Oracle Production database connections by external configuration properties in spring. 数据源

java - Spring Boot schema.sql - 重启时删除数据库模式