我尝试过同时使用ReactiveAuthenticationManager
和WebFilter
。在这两种情况下,执行流程都是这样的:
@Component
@RequiredArgsConstructor
public class JwtReactiveAuthenticationManager implements ReactiveAuthenticationManager {
private final JwtTokenProvider jwtTokenProvider;
private final UserRepository userRepository;
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String token = authentication.getCredentials().toString();
if (!jwtTokenProvider.validateToken(token)) {
System.out.println("Invalid token");
return Mono.empty();
}
String username = jwtTokenProvider.getUsernameFromToken(token);
return userRepository.findByEmail(username)
.switchIfEmpty(Mono.error(new RuntimeException("User not found")))
.map(user -> {
System.out.println("hydrated user from token. File is JRAM");
System.out.println(user); // this prints user
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
user.getUsername(),
null,
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))
);
return authenticationToken;
});
}
}
如上所述,token 已解码,并且用户已正确补水。我相信问题源于将其绑定到ReactiveSecurityContextHolder
。我尝试了以下不同变体:
SecurityContextImpl securityContext = new SecurityContextImpl(authentication);
Context context = ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext));
在一个实例中,我尝试设置安全上下文并将其返回给 mono。在另一个实例中,我尝试直接在 上设置身份验证ReactiveSecurityContextHolder.withAuthentication
。没有成功。当我使用 时ReactiveAuthenticationManager
,我还尝试过ServerSecurityContextRepository
@Override
public Mono<SecurityContext> load(ServerWebExchange swe) {
String authHeader = swe.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
return authenticationManager.authenticate(auth).map(SecurityContextImpl::new);
} else {
return Mono.empty();
}
}
没有帮助。尝试在ReactiveSecurityContextHolder
后续的 mono 方法中从 读取身份验证失败,并显示NullPointerException
。所以我猜设置中断了,但我无法调试它switchIfEmpty
,onErrorResume
只能打印出他们给出的所有内容。
关于该主题的大多数 Stack Overflow 答案都已过时,使用已弃用的方法。此外,在检索用户时,这些方法对我都不起作用。身份验证可能失败,但在某些时候,我可以访问用户参数,尽管它是空白的。其他时候,请求只是以 401 退出
以下是安全配置
http
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
// bunch of stuff
return config;
}))
/*.authenticationManager(authenticationManager)
.securityContextRepository(securityContextRepository)*/
.authorizeExchange(authorizeExchangeSpec -> {
authorizeExchangeSpec.pathMatchers(
"api/v1/user/login",
"api/v1/user/register","webjars/**",
"/v3/api-docs/**", "/swagger-ui.html",
"/swagger-ui/**").permitAll();
authorizeExchangeSpec.anyExchange().authenticated();
})
.addFilterAt(jwtAuthenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.build();
请帮助说明将我的用户传递到安全上下文并从控制器方法中检索它的必要步骤。我使用的是 Spring Boot 3.3.4。谢谢