2

当用户无权访问它们时,我需要发布任何 Micronaut 控制器的响应并消除响应正文中的项目。

在一个阻塞的世界中,我会像这样实现它

protected MutableHttpResponse<?> doFilterOnce(HttpRequest<?> request, ServerFilterChain chain) {

        // If Micronaut Security rejected the request simpy do nothing
        if (request.getAttribute(SecurityFilter.REJECTION).isPresent()) {
            log.debug("Request was previously rejected. Not going to contact PDP");
            return chain.proceed(request);
        }

        HttpMethod method = request.getMethod();

        if (method.equals(GET) || method.equals(HEAD)) {

            MutableHttpResponse<?> response = chain.proceed(request);

            if (response.getBody().isPresent()) {
                // iterate through the body

                Object theBody = response.getBody().get();

                if (theBody instanceof Collection) {

                    Collection<?> iterable = (Iterable<?>) theBody;

                    // select all elements that are rejected. This is a blocking call.
                    List<?> collect = iterable.stream().filter(item -> mySecService.isAllowed(item) == false).collect(Collectors.toList());
                    // remove them
                    iterable.removeAll(collect);
                    // reset the body
                    response.body(iterable);
                }
            }

        } else {
            return chain.proceed(request)
        }
        return response;
    }

Micronaut 指出

过滤器在事件循环中执行,因此阻塞操作必须卸载到另一个线程池。

因此在现实世界中它需要 mit 返回

  1. 可流动的
  2. 以反应的方式实现上面的代码

这是我到目前为止所做的。

if (method.equals(GET) || method.equals(HEAD)) {
    // post process
    return Flowable.fromPublisher(chain.proceed(request))
            .doNext(response -> {
                Optional<?> body = response.getBody();

                if (body.isPresent()) {
                     // how can I continue here an process the response body collection?
                }
            });
}

有人可以给我一个提示如何继续处理响应正文,进行安全检查,删除项目并重置新正文吗?

4

1 回答 1

1

在响应式世界中,我们将不得不使用Flowable. Stream给定用于检查是否允许某个项目的方法的反应式实现(例如mySecService::isAllowedReactive返回 a 的某个方法Single<Boolean>),我们可以使用Flowable#concatMapSingle创建一个Flowable告诉我们用户是否可以看到第 n 个项目的 a。我们可以将其与原始的可迭代对象结合起来以过滤掉不允许的项目。当然,像这样嵌套反应类型需要使用flatMap.


@Override
protected Publisher<MutableHttpResponse<?>> doFilterOnce(HttpRequest<?> request, ServerFilterChain chain) {
    // If Micronaut Security rejected the request simpy do nothing
    if (request.getAttribute(SecurityFilter.REJECTION).isPresent()) {
        log.debug("Request was previously rejected. Not going to contact PDP");
        return chain.proceed(request);
    }
    HttpMethod method = request.getMethod();
    return Flowable.fromPublisher(chain.proceed(request)).flatMap(response -> {
        if (method.equals(HttpMethod.GET) || method.equals(HttpMethod.HEAD)) {
            if (response.getBody().isPresent()) {
                // iterate through the body
                Object theBody = response.getBody().get();
                if (theBody instanceof Collection) {
                    Collection<?> iterable = (Collection<?>) theBody;



                    // find which elements are not allowed.
                    Flowable<Boolean> isElementAllowed = Flowable.fromIterable(iterable)
                            .concatMapSingle(mySecService::isAllowedReactive);



                    // filter out forbidden elements
                    Single<ArrayList<? super Object>> allowedElementsSingle = isElementAllowed
                            .zipWith(iterable, (isAllowed, item) -> {
                                if (isAllowed) {
                                    return Optional.of(item);
                                } else {
                                    return Optional.empty();
                                }
                            })
                            .filter(Optional::isPresent)
                            .map(Optional::get)
                            .collect(ArrayList::new, ArrayList::add);



                    return allowedElementsSingle.flatMapPublisher(allowedElements -> {
                        // reset the body
                        response.body(allowedElements);
                        return Flowable.just(response);
                    });
                }
            }
        }
        return Flowable.just(response);
    });
}

于 2021-01-06T07:42:39.057 回答