-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Provide a way to customize the default RequestCache without replacing the entire implementation #15707
Comments
Hi @eric-creekside, thanks for the report. I'd like to clarify what you are asking to see what can be done to help: Do you want an easier way to provide your own HttpSessionRequestCache myCache = new HttpSessionRequestCache();
myCache.setRequestMatcher(myRequestMatcher);
http.requestCache(cache -> cache.requestCache(myCache)) Or do you want to customize the
I don't think this is something that we usually do, I don't remember any other configurer that does that. And, as you mentioned, it would require cast and other stuff that won't make it easier to configure. With that said, I think it would be fine to add a |
In the end, what I'm hoping for is a way to extend the default Here's what I had to do to just to add my own API pattern to be excluded: private RequestMatcher createSavedRequestMatcher(HttpSecurity http) {
List<RequestMatcher> matchers = new ArrayList<>();
RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.*"));
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
@SuppressWarnings("unchecked")
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
if (isCsrfEnabled) {
RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
matchers.add(0, getRequests);
}
matchers.add(notFavIcon);
matchers.add(notMatchingMediaType(http, MediaType.APPLICATION_JSON));
matchers.add(notXRequestedWith);
matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA));
matchers.add(notMatchingMediaType(http, MediaType.TEXT_EVENT_STREAM));
// Exclude our API endpoints from the matcher
RequestMatcher notAPI = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/api/**", "GET"));
matchers.add(notAPI);
return new AndRequestMatcher(matchers);
} Everything except the 2 lines below the |
Hi @eric-creekside, I brought this to the team's attention and I'll list here some thoughts. Allowing the customization of the default request matcher is not something that we want to do. The DSL is limited to the configurations that cover the majority of use cases. Usually, customizations like this are achieved by creating a bean and injecting it into the DSL. We could introduce a static factory method that could be reused, or, we could post-process the default Given that the solutions thought so far won't be flexible to cover "all cases", I'd like to propose that we keep this ticket open and see the community's interest in this (by gathering upvotes). Let me know what you think. |
I'm skeptical the team will want to, but I think simply making Also, I'm curious about this statement you made:
Can you clarify (maybe with an example) what you mean? |
I think that a potential solution for you is to create a delegator like so: public class MyRequestCache implements RequestCache {
private final RequestCache delegate;
public MyRequestCache(RequestCache delegate) {
this.delegate = delegate;
}
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
if (myCustomRequestMatchingPasses) {
this.delegate.saveRequest(request, response);
}
}
public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response) {
return this.delegate.getRequest(request, response);
}
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response) {
return this.delegate.getMatchingRequest(request, response);
}
public void removeRequest(HttpServletRequest request, HttpServletResponse response) {
this.delegate.removeRequest(request, response);
}
] And then wrap the configured request cache using an object post processor: http
// ...
.requestCache((cache) -> cache
.addObjectPostProcessor(new ObjectPostProcessor<RequestCache>() {
@Override
RequestCache postProcess(RequestCache delegate) {
return MyRequestCache(delegate);
}
});
)
// ... This will allow for your custom request matching criteria to be executed and then the Spring Security internal one. |
Spring Security 6.2.5
Without any customization, the default
RequestCache
isHttpSessionRequestCache
(created by private methods inRequestCacheConfigurer
). For some situations, it would be necessary to customize that cache. An example I have run into is needing to extend the cache'sRequestMatcher
to exclude certain requests from being cached (see this SO question for specifics).As far as I can see, the only customization option for a typical
SecurityFilterChain
bean is to completely replace theRequestCache
object viaRequestCacheConfigurer<HttpSecurity>.requestCache()
. That's far from ideal as many applications will want the default configured cache with only minor changes. Since the configurer's methods that create or use the default are all private, that's not currently possible.It would be useful for
RequestCacheConfigurer
to expose a way to get to the default cache, so the application can customize it. Even if it required a cast, that would likely be a "lesser of 2 evils" choice for many developers.The text was updated successfully, but these errors were encountered: