Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose mapped handler as an exchange attribute [SPR-15564] #20123

Closed
spring-issuemaster opened this issue May 18, 2017 · 12 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented May 18, 2017

Jon Schneider opened SPR-15564 and commented

For Spring Metrics, Spring Cloud Sleuth, and possible security, there is a need for a corollary to the HandlerMethod concept from webmvc.

If we can somehow retrieve the HandlerMethod from a WebFilter, it should be sufficient.

As long as there is a way to register a WebFilter globally for all annotation-based Webflux request mappings, there will be no need for a HandlerInterceptor corollary.


Affects: 5.0 RC1

Referenced from: commits 67330df

1 votes, 6 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jun 12, 2017

Rossen Stoyanchev commented

Jon Schneider would exposing the HandlerMethod through a request attribute be enough for you? It might be simpler since you'd only register a WebFilter and access the request attribute after the filter chain completes.

This fits with what we provide. Currently HandlerMapping defines several attributes to expose information and we would add one more. Now that we've revised the mapping process in WebFlux extensively this part could use some cleanup too. We could expose a single attribute (some info object) that contains mapping details.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jun 12, 2017

Jon Schneider commented

I see that HandlerMethod has the bean and method on it, so that will work great!

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jun 29, 2017

Rossen Stoyanchev commented

Sorry for taking so long. There is now a HandlerMapping#BEST_MATCHING_HANDLER_ATTRIBUTE attribute. See if that works for you.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 8, 2017

Igal commented

I see that this issue was done and from the above comments i understand that BEST_MATCHING_HANDLER_ATTRIBUTE will be available in the WebFilters.
But it seems from the code that this attribute is only being populated at: org.springframework.web.reactive.DispatcherHandler#handle

but that code occurs after the webfilter were performed?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 10, 2017

Igal commented

@Rossen Stoyanchev please advice

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Rossen Stoyanchev commented

but that code occurs after the webfilter were performed?

In this case "after" is ambiguous because the request is handled asynchronously. If you mean after the filter chain returns, this is expected. Most likely you need to use one of the operators on Mono<Void> to add "after logic". Possibly doOnNext or flatMap, then(Mono<Void>, etc.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Igal commented

Just to be sure my question is clear:

Im writing a Security filter, which will be used if the user is authorized to access the api method:

@Override
public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain) {
    HandlerMethod handlerMethod = exchange.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE);

    // Make some authorization check on the handlerMethod and decide whether to continue or throw exception if not authorized
    return chain.filter(exchange);
}

The problem is that HandlerMethod value is null in that point. the code which populates that attribute occurs after all web filters are already executed.
Any idea where/how do i need this code to run so i would have the handlerMethod populated?

Thanks

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Doron Gold commented

To clarify Igal's point:

We are trying to use this feature for authorization.
if exchange.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE); can only be called after the handler method was already invoked and a response was sent back to the caller, that is too late.
We are trying to figure if there is a way to use this feature in such a way that can break the flow and not invoke the handler method in case authorization logic in our WebFilter finds that the user is not authorized to run that handler method.

Currently we use aop with custom annotations, but we prefer to use a WebFilter.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Rossen Stoyanchev commented

Okay I see. That is before rather than after... Well, in that case the attribute can't help much. It simply reflects what handler was chosen after the fact. In other words there is no way to know how the request will be mapped before the mapping takes place.

I believe Spring Security has a work in progress on method-based security that Rob Winch would be able to say more about what's coming. I presume you also have URL-based security and this is in addition?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Doron Gold commented

We don't have URL-based security.
Currently Spring Security only supports URL-based security. That requires creating a URL-to-roles mapping in a different place than the Controller methods that are being mapped.
We find this too error prone, it is not possible to see just by looking at Controller methods, who is allowed activate each method.

Therefore we chose to use annotations.
When a method has an annotation that expresses authorization constraints, it is easy to follow. It also mitigates the risk of forgetting to to protect some methods.

We are currently using a custom @Secure annotation which is similar to the @Secure annotation provided by Spring Security.
We use AOP to intercept Controller method calls and do authorization checks before the actual method invocation proceeds.

We were hoping that this feature would allow us to replace our AOP Aspect with a WebFilter that does the same: runs authorization logic that based on a custom annotation on the handler method, decides if it is allowed to be called.

Since this feature allows for getting the handler method only after it has been invoked, we will stay with AOP.

We are following the Spring Security project to see when annotation based security is implemented.

Thanks!

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 14, 2017

Doron Gold commented

Just to clarify, Spring Security does provide annotation base security with its @Secure annotation.
However, this does not yet work with Spring WebFlux.
That is why we implemented a similar mechanism ourselves.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 5, 2018

Rob Winch commented

Doron Gold This thread is quite old, but I wanted to ensure you (and others reading) were aware that reactive method security is provided in Spring Security 5.0.0.RELEASE which is available in Maven central. See https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-erms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.