我想获取所有经过身份验证的用户的列表。
我学习了基本的 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 上的主题非常罕见,我找不到完整的示例。类似的帖子尚未得到答复( 48804780 、 58925128 )。
抱歉,我是 Spring 新手,SimpUserRegistry 是使用 Spring 列出用户的正确方法吗?如果可以的话,该如何正确使用呢?谢谢。
最佳答案
在您的问题中,您正在尝试一些事情:
- 您正在使用允许的用户列表(在您的例子中,用户名为
u
)设置InMemoryUserDetailsManager
。 - 您正在使用
SimpUserRegistry
通过 Spring 消息传递(例如使用 WebSockets)获取所有已连接用户的列表。
如果您只是想获取所有用户的列表,并且没有使用 WebSocket,那么第二种方法将不起作用。
如果您尝试获取存储在 InMemoryUserDetailsManager
中的所有用户的列表,那么答案是不可能获取该列表。 InMemoryUserDetailsManager
使用内存中的Map
来存储所有用户,并且它不会公开该列表。
如果您确实想要这样的列表,则必须创建一个自定义内存中UserDetailsService
,例如:
@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"));
}
}
在此示例中,InMemoryUser
是 UserDetails
接口(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/