RSocket与Spring Security整合

Posted Spring微服务

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RSocket与Spring Security整合相关的知识,希望对你有一定的参考价值。

这期Spring Tips内容是RSocket与Spring Security整合(视频正在审核)

创建工程

  • greetings-service

    在 start.spring.io 选择 2.3.0 M2 版本 Spring Boot,依赖项如下

    Lombok

    RSocket

    Spring Security

  • greetings-client

    客户端的依赖项也是

    Lombok

    RSocket

    Spring Security

服务端应用

GreetingsServiceApplication.java

 // 省略导入
 // 一个简单的,基于用户名和密码的“问候”应用
 // 简单起见,所有类都写在一个文件里
 @SpringBootApplication
 public class GreetingsServiceApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(GreetingsServiceApplication.class, args);
    }
 }
 
 @Configuration
 @EnableRSocketSecurity
 class RSocketSecurityConfiguration {
 
     @Bean
     RSocketMessageHandler messageHandler(RSocketStrategies strategies) {
         RSocketMessageHandler mh = new RSocketMessageHandler();
         mh.getArgumentResolverConfigurer()
            .addCustomResolver(new AuthenticationPrincipalArgumentResolver());
         mh.setRSocketStrategies(strategies);
         return mh;
    }
 
     // 授权
     @Bean
     PayloadSocketAcceptorInterceptor authorization(RSocketSecurity security) {
         return security
                .authorizePayload(spec -> spec
                        .route("greetings")
                        .authenticated()
                        .anyExchange()
                        .permitAll())
                .simpleAuthentication(Customizer.withDefaults())
                .build();
    }
 
     // 用户认证 Authentication
     @Bean
     MapReactiveUserDetailsService authentication() {
         UserDetails jlong = User.withDefaultPasswordEncoder().username("jlong")
            .password("pw").roles("USER").build();
         UserDetails rwinch = User.withDefaultPasswordEncoder().username("rwinch")
            .password("pw").roles("ADMIN", "USER").build();
         return new MapReactiveUserDetailsService(jlong, rwinch);
    }
 }
 
 // DTO
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 class GreetingResponse {
     private String message;
 }
 
 @Controller
 class GreetingController {
 
     @MessageMapping("greetings")
     Flux<GreetingResponse> greet(@AuthenticationPrincipal Mono<UserDetails> user) {
         return user
                .map(UserDetails::getUsername)
                .flatMapMany(GreetingController::greet);
    }
 
     private static Flux<GreetingResponse> greet(String name) {
         return Flux.fromStream(
                 Stream.generate(() ->
                 new GreetingResponse("Hello " + name + " @ " +
                 Instant.now().toString())))
                .delayElements(Duration.ofSeconds(1));
    }
 }

服务端的配置文件:application.properties

 spring.rsocket.server.port=8888

客户端应用

GreetingsClientApplication.java

 @SpringBootApplication
 @Log4j2
 public class GreetingsClientApplication {
 
     @SneakyThrows
     public static void main(String[] args) {
         SpringApplication.run(GreetingsClientApplication.class, args);
         System.in.read(); // 让程序不要结束
    }
 
     private final MimeType mimeType =
             MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
     private final UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("jlong", "pw");
 
     // 配置所用编码器
     @Bean
     RSocketStrategiesCustomizer rSocketStrategiesCustomizer() {
         return strategies -> strategies.encoder(new SimpleAuthenticationEncoder());
    }
 
     // 相当于客户端
     @Bean
     RSocketRequester rSocketRequester(RSocketRequester.Builder builder) {
         return builder
                 //.setupMetadata(this.credentials, this.mimeType)
                .connectTcp("localhost", 8888)
                .block();
    }
 
     // 应用就绪时通过RSocket向localhost:8888/greetings发起请求
     // 并将响应消息通过日志输出到控制台
     @Bean
     ApplicationListener<ApplicationReadyEvent> ready(RSocketRequester greetings) {
         return event -> greetings
                .route("greetings")
                .metadata(this.credentials, this.mimeType)
                .data(Mono.empty())
                .retrieveFlux(GreetingResponse.class)
                .subscribe(gr -> log.info("secured response: " + gr.toString()));
    }
 }
 
 // DTO
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 class GreetingResponse {
     private String message;
 }

结束

感觉直接看代码也挺好理解的,就不勉强添加太多文字说明了。


以上是关于RSocket与Spring Security整合的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Security-Oauth整合Spring-Security,拦截器

Spring Security 整合 JSON Web Token(JWT)

spring boot整合 spring security之会话管理

Spring RSocket:基于服务注册发现的 RSocket 负载均衡

Spring Boot:整合Spring Security

spring boot 整合spring security中spring security版本升级的遇到的坑