Java 函数内部。映射执行两次
我正在尝试在SpringBoot2.2.5.RELEASE上构建一个身份验证服务,使用反应堆栈。 几个小时以来我一直在挠头 执行Java 函数内部。映射执行两次,java,spring-boot,spring-security,spring-webflux,project-reactor,Java,Spring Boot,Spring Security,Spring Webflux,Project Reactor,我正在尝试在SpringBoot2.2.5.RELEASE上构建一个身份验证服务,使用反应堆栈。 几个小时以来我一直在挠头 执行.map中的函数两次。 @覆盖 公共Mono findByUsername(最终字符串用户名){ System.out.println(“findByUsername被调用”); 返回Mono.fromSupplier(()->userRepository.findByUsername(userName)).subscribeOn(调度器) .switchIfEmpty
.map
中的函数两次。
@覆盖
公共Mono findByUsername(最终字符串用户名){
System.out.println(“findByUsername被调用”);
返回Mono.fromSupplier(()->userRepository.findByUsername(userName)).subscribeOn(调度器)
.switchIfEmpty(Mono.error(新用户名NotFoundException(“错误凭据”))
.map(用户->{
System.out.println(“内部findByUsername”);
新建AccountStatusUserDetailsChecker()。检查(用户);
返回(UserDetails)用户;
}).log();
}
以下是非反应性postgres回购协议(因此是上述代码中的供应商)
@存储库
@交易的
公共接口用户存储库扩展了JpaRepository{
/**
*按用户名查找用户
*
*@param username用户名
*@return用户对象
*/
用户findByUsername(字符串用户名);
}
下面是findByUsername
函数的调用方:
@覆盖
公共Mono加载(ServerWebExchange swe){
System.out.println(“调用加载”);
final ServerHttpRequest request=swe.getRequest();
最终字符串username=request.getHeaders().getFirst(CustomHTTPHeaders.Keys.username);
最终字符串密码=request.getHeaders().getFirst(CustomHTTPHeaders.Keys.password);
final AbstractAuthenticationToken auth=新用户名PasswordAuthenticationToken(用户名、密码);
返回userDetailService.findByUsername(用户名).map(详细信息->{
System.out.println(“isnide flatmap”+Thread.currentThread().getName());
授权设置详细信息(详细信息);
SecurityContext SecurityContext=SecurityContextHolder.getContext();
if(passwordEncoder.matches(auth.getCredentials().toString(),details.getPassword())){
securityContext.setAuthentication(新用户名密码AuthenticationToken(details.getUsername()、details.getPassword()、details.getAuthories());
返回securityContext;
}
setAuthentication(新用户名PasswordAuthenticationToken(details.getUsername(),null));
返回securityContext;
});
输出:
load called
findByUsername called
2020-03-17 20:04:58.281 INFO 44648 --- [oundedElastic-3] reactor.Mono.Map.1 : onSubscribe(FluxMap.MapSubscriber)
2020-03-17 20:04:58.283 INFO 44648 --- [oundedElastic-3] reactor.Mono.Map.1 : request(unbounded)
inside findByUsername
2020-03-17 20:04:58.466 INFO 44648 --- [oundedElastic-4] reactor.Mono.Map.1 : onNext(User(email=william@gmail.com, username=admin, password={bcrypt}$2a$10$EOs8VROb14e7ZnydvXECA.4LoIhPOoFHKvVF/iBZ/ker17Eocz4Vi, enabled=true, accountLocked=false, accountExpired=false, credentialsExpired=false, roles=[Role(name=role_admin, permissions=[Permission(name=CREATE_USER), Permission(name=UPDATE_USER), Permission(name=READ_USER), Permission(name=DELETE_USER), Permission(name=VERIFY_TOKEN)])]))
isnide flatmap boundedElastic-4
2020-03-17 20:04:58.598 INFO 44648 --- [oundedElastic-4] reactor.Mono.Map.1 : cancel()
2020-03-17 20:04:58.604 INFO 44648 --- [oundedElastic-4] reactor.Mono.Map.1 : onSubscribe(FluxMap.MapSubscriber)
2020-03-17 20:04:58.604 INFO 44648 --- [oundedElastic-4] reactor.Mono.Map.1 : request(unbounded)
inside findByUsername
2020-03-17 20:04:58.608 INFO 44648 --- [oundedElastic-3] reactor.Mono.Map.1 : onNext(User(email=william@gmail.com, username=admin, password={bcrypt}$2a$10$EOs8VROb14e7ZnydvXECA.4LoIhPOoFHKvVF/iBZ/ker17Eocz4Vi, enabled=true, accountLocked=false, accountExpired=false, credentialsExpired=false, roles=[Role(name=role_admin, permissions=[Permission(name=CREATE_USER), Permission(name=UPDATE_USER), Permission(name=READ_USER), Permission(name=DELETE_USER), Permission(name=VERIFY_TOKEN)])]))
isnide flatmap boundedElastic-3
2020-03-17 20:04:58.716 INFO 44648 --- [oundedElastic-3] reactor.Mono.Map.1 : onComplete()
Web安全配置:
package com.turtlemint.authservice.config;
导入com.turtlemint.authservice.controller.SecurityContextRepository;
导入com.turtlemint.authservice.service.impl.AuthenticationManager;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.context.annotation.Bean;
导入org.springframework.http.HttpMethod;
导入org.springframework.http.HttpStatus;
导入org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
导入org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
导入org.springframework.security.config.web.server.ServerHttpSecurity;
导入org.springframework.security.crypto.factory.PasswordEncoderFactorys;
导入org.springframework.security.crypto.password.PasswordEncoder;
导入org.springframework.security.web.server.SecurityWebFilterChain;
导入reactor.core.publisher.Mono;
/**
*
*此类持有spring安全配置
*
*
*@作者praveenkamath
*创建于20年3月9日
*@自1.0.0以来
*/
@启用WebFluxSecurity
@EnableReactiveMethodSecurity
公共类Web安全配置{
@自动连线
AuthenticationManager AuthenticationManager;
@自动连线
私人证券内容临时存储证券内容临时存储;
/**
*提供密码编码器
*
*@返回密码编码器实例
*/
@豆子
公共密码编码器PasswordEncoder(){
返回PasswordEncoderFactorys.createDelegatingPasswordEncoder();
}
/**
*为安全性配置端点
*
*@param http安全性
*/
@豆子
公共安全WebFilterChain安全WebFilterChain(最终服务器HttpSecurity http){
返回http.cors().disable()
.例外处理()
.authenticationEntryPoint((swe,e)->Mono.fromRunnable(()->{
swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
})).accessDeniedHandler((swe,e)->Mono.fromRunnable(()->{
swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
})).及()
.csrf().disable()
.authenticationManager(authenticationManager)
.securityContextRepository(securityContextRepository)
.授权交易所()
//.pathMatchers(“/api/**”).permitAll()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.anyExchange().authenticated()
.及()
.build();
}
}
不知道这是ProjectReactor中的bug还是我的代码中的bug。
请帮助。尝试将
从供应商
切换到从可调用
尝试在映射
之前添加publishOn(Schedulers.newParallel(“any”)
。我假设userRepository.findByUsername(userName)
与jdbc池相关,在db查询之后,它会使您的boundedElastic-4
被取消。