1

我尝试使用带有嵌入式tomcat的spring boot webApplication和来自reactor的netServer开发一个“混合”服务器,以扩大我的Rest Api。没有 Spring 控制器,所有传入的请求都由 netServer 处理。无论如何,我都希望有一个使用 spring security 的登录页面,记住我的设施来验证用户并使用此身份验证来保护 reactor netServer 上的传入请求。

根据本教程reactor thumbmailer,我开始实现 netServer

这是我的网络服务器:

NetServer<FullHttpRequest, FullHttpResponse> server = new TcpServerSpec<FullHttpRequest, FullHttpResponse>(NettyTcpServer.class)
        .env(env)
        .dispatcher("sync")
        .listen(8080)
        .options(opts)
        .consume(ch -> {
          // attach an error handler
          ch.when(Throwable.class, UserController.errorHandler(ch));

          // filter requests by URI
          Stream<FullHttpRequest> in = ch.in();

          // serve image thumbnail to browser
          in.filter((FullHttpRequest req) -> req.getUri().startsWith(UserController.GET_USER_PROFILE))
            .consume(UserController.getUserProfile(ch));

        })
        .get();

因此,当用户尝试加载他的个人资料时,传入的请求由 userController 处理:

public static Consumer<FullHttpRequest> getUserProfile(NetChannel<FullHttpRequest, FullHttpResponse> channel) {

    UserService userService = StaticContextAccessor.getBean(UserService.class);

    return req -> {
        try {
            LoginDTO login = RestApiUtils.parseJson(LoginDTO.class, RestApiUtils.getJsonContent(req));


            DefaultFullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, OK);

            String result = userService.loadUserProfile(login);
            resp.headers().set(CONTENT_TYPE, "application/json");
            resp.headers().set(CONTENT_LENGTH, result.length());
            resp.content().writeBytes(result.getBytes());
            channel.send(resp);
        } catch (Exception e) {
            channel.send(badRequest(e.getMessage()));
        }
    };

}

这是 hack:getUserProfile 是一个静态方法,所以我不能使用 GlobalMethodSecurity 来保护它。然后我使用 StaticContextAccessor 在这个控制器中注入一个 userService :

@Component
public class StaticContextAccessor {

  private static StaticContextAccessor instance;

  @Autowired
  private ApplicationContext applicationContext;

  @PostConstruct
  public void registerInstance() {
      instance = this;
  }

  public static <T> T getBean(Class<T> clazz) {
      return instance.applicationContext.getBean(clazz);
  }

}

用户服务:

@Service
@PreAuthorize("true")
public class UserServiceImpl implements UserService{

  public String loadUserProfile(LoginDTO login){

    //TODO load profile in mongo

    return new GsonBuilder().create().toJson(login);
  }

}

该服务由spring管理,所以我想我可以在它上面使用spring GlobalMethodSecurity(我仍在开发这部分,但我不确定这是保护我的netServer的最佳方式)

有没有更简单的方法在 reactor netServer 上使用 Spring 安全性???我的第一个网站版本是使用 nodeJS 开发的,以处理许多并发用户,我尝试使用 JVM nio 解决方案对其进行重构。那么 spring / reactor / netty 是拥有高度可扩展服务器的一个很好的解决方案,还是我应该使用类似 play 的东西!或 vertx.io ?

太感谢了

4

1 回答 1

1

您是否尝试NetServer过从 JavaConfig@Bean方法中引导您?就像是:

@Configuration
@EnableReactor
class AppConfig {

  public Function<NetChannel, UserController> users() {
    return new UserControllerFactory();
  }

  @Bean
  public NetServer netServer(Environment env, Function<NetChannel, UserController> users) {
    return new TcpServerSpec(NettyTcpServer.class)
      .env(env)
      .dispatcher("sync")
      .listen(8080)
      .options(opts)
      .consume(ch -> {
        // attach an error handler
        ch.when(Throwable.class, UserController.errorHandler(ch));

        // filter requests by URI
        Stream<FullHttpRequest> in = ch.in();

        // serve image thumbnail to browser
        in.filter((FullHttpRequest req) -> req.getUri().startsWith(UserController.GET_USER_PROFILE))
          .consume(users.apply(ch));
      })
      .get();
  }

}

这应该保留您的 Spring Security 支持,并使您能够将处理程序共享为 bean,而不是作为静态方法的返回值。通常,您在 Reactor TCP 应用程序中需要做的几乎所有事情都可以使用 bean 和注入以及通过将NetServerbean 本身返回为 bean 来完成。

于 2014-07-29T22:07:28.637 回答