如何使用弹簧安全保护reactor netServer?

时间:2014-07-27 02:58:01

标签: spring-security netty spring-boot reactor

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

根据本教程reactor thumbmailer

,我开始实现netServer

这是我的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);
  }

}

UserService:

@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开发的,用于处理许多concurent用户,我尝试使用JVM nio解决方案对其进行重构。 那么spring / reactor / netty是一个很好的解决方案,有一个高度可扩展的服务器,或者我应该使用像玩的东西!或者vertx.io?

非常感谢

1 个答案:

答案 0 :(得分:1)

您是否尝试过在JavaConfig NetServer方法中引导@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和注入来完成,并将NetServer作为一个bean本身来恢复。