Я пытаюсь создать несколько кодов безопасности webflux, как показано ниже,
@Configuration
@EnableWebFluxSecurity
public class BlogWebFluxSecurityConfig {
@Bean
public MapReactiveUserDetailsService userDetailsService() {
UserDetails userWebFlux = User.withUsername("joseph").password(passwordEncoder().encode("password")).roles("USER").build();
return new MapReactiveUserDetailsService(userWebFlux);
}
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/route/user/all", "/route/post/all").permitAll()
.pathMatchers(HttpMethod.GET, "/route/user/**", "/route/post/**").hasRole("USER")
.anyExchange().authenticated()
.and()
.httpBasic();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
, а также создать клиентские коды webflux с классом WebClient.Я использую http базовую аутентификацию.В методе HTTP GET базовая аутентификация http работает успешно.Это коды веб-клиентов, которые хорошо работают.
client.get().uri("/route/post/id/{id}", 10).accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, basicAuthHeader).exchange()
.flatMap(response -> response.bodyToMono(Post.class))
.subscribe(p -> System.out.println("GET by Id : " + p.getUser().getUsername() + ":" + p.getTitle()));
Но при использовании методов HTTP.POST и HTTP.PUT базовая аутентификация http не работает, даже выдает исключение.
public class WebFluxBlogClient {
private WebClient client = WebClient.create("http://localhost:8080");
String basicAuthHeader = "basic " + Base64Utils.encodeToString(("joseph" + ":" + "password").getBytes());
public void functionOnSecurityDocument() {
Map<String, String> mapUser = new HashMap<String, String>();
mapUser.put("username", "joseph");
mapUser.put("password", "password");
client.post().uri("/route/user/login").accept(MediaType.APPLICATION_JSON).body(Mono.just(mapUser), Map.class)
.header(HttpHeaders.AUTHORIZATION, basicAuthHeader).exchange()
.map(ClientResponse::statusCode).subscribe(response -> System.out.println("Login : " + response.getReasonPhrase()));
User user = new User("0005", 4L, "jane", "password", "aaa@bbb.com", "누나", "USER");
client.post().uri("/route/user/create").accept(MediaType.APPLICATION_JSON).body(Mono.just(user), User.class)
.header(HttpHeaders.AUTHORIZATION, basicAuthHeader).exchange()
.map(ClientResponse::statusCode).subscribe(response -> System.out.println("User Creation: " + response.getReasonPhrase()));
client.put().uri("/route/post/{id}/{content}", 7, "test sentences....")
.accept(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, basicAuthHeader).exchange().flatMap(response -> response.bodyToMono(Post.class))
.subscribe(p -> System.out.println("EDIT by Id : " + p.getUser().getUsername() + ":" + p.getBody()));
}
}
Значения ответа
Login : Forbidden
User Creation: Forbidden
2019-07-08 12:46:16.443 WARN 4800 --- [ctor-http-nio-3] io.netty.util.ReferenceCountUtil : Failed to release a message: DefaultLastHttpContent(data: PooledSlicedByteBuf(freed), decoderResult: success)
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:74) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:138) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:100) ~[netty-buffer-4.1.36.Final.jar:4.1.36.Final]
at io.netty.handler.codec.http.DefaultHttpContent.release(DefaultHttpContent.java:94) ~[netty-codec-http-4.1.36.Final.jar:4.1.36.Final]
at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at io.netty.util.ReferenceCountUtil.safeRelease(ReferenceCountUtil.java:113) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:120) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:617) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:534) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
2019-07-08 12:46:16.443 WARN 4800 --- [ctor-http-nio-3] reactor.netty.channel.FluxReceive : [id: 0xdfda1db5, L:0.0.0.0/0.0.0.0:54009] An exception has been observed post termination, use DEBUG level to see the full stack: reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/plain' not supported for bodyType=com.aaa.blog.wf.model.Post
Я понятия не имею, что означает исключение.Я хочу знать, как применить базовую аутентификацию http для HTTP.POST и HTTP.PUT методом webflux webclient.Любой ответ будет оценен.Спасибо
== Обновленные детали ==
Я изменяю конфигурацию безопасности, как показано ниже, но она не срабатывает.
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/route/user/all", "/route/post/all").permitAll()
.pathMatchers(HttpMethod.GET, "/route/user/id/**", "/route/user/username/**", "/route/user/email/**").hasRole("USER")
.pathMatchers(HttpMethod.POST, "/route/user/login", "/route/user/create", "/route/post/create").hasRole("USER")
.anyExchange().authenticated()
.and()
.httpBasic();
return http.build();
}
Для вашей информации яприсоедините класс маршрутизатора.
@Bean
public RouterFunction<ServerResponse> routesUser(UserHandler handler) {
return RouterFunctions.route(RequestPredicates.GET("/route/user/all"), handler::findAll)
.andRoute(RequestPredicates.GET("/route/user/id/{id}"), handler::findById)
.andRoute(RequestPredicates.GET("/route/user/username/{username}"), handler::findByUsername)
.andRoute(RequestPredicates.GET("/route/user/email/{email}"), handler::findByEmail)
.andRoute(RequestPredicates.POST("/route/user/create"), handler::register)
.andRoute(RequestPredicates.POST("/route/user/login"), handler::authenticate);
}
Но выдают те же сообщения об ошибках, как показано ниже,
Login : Forbidden
User Creation: Forbidden
В моей конфигурации SecurityWebFilterChain есть некоторые проблемы?Пожалуйста, пришлите мне свой ответ.