Prefer dispatcher context for authorize tag beans#18822
Prefer dispatcher context for authorize tag beans#18822wonderfulrosemari wants to merge 1 commit intospring-projects:mainfrom
Conversation
Signed-off-by: wonderfulrosemari <whwlsgur1419@naver.com>
jzheaux
left a comment
There was a problem hiding this comment.
Thanks, @wonderfulrosemari, for the PR! I've left feedback inline.
| */ | ||
| public abstract class AbstractAuthorizeTag { | ||
|
|
||
| private static final String DISPATCHER_SERVLET_CONTEXT_ATTRIBUTE = "org.springframework.web.servlet.DispatcherServlet.CONTEXT"; |
There was a problem hiding this comment.
Let's please make this public so it's clear that Spring Security expects applications to set this attribute themselves. WebAttributes is a good home for this. Please also take a look at the naming convention used in WebAttributes for both the name and the value.
| */ | ||
| public abstract class AbstractAuthorizeTag { | ||
|
|
||
| private static final String DISPATCHER_SERVLET_CONTEXT_ATTRIBUTE = "org.springframework.web.servlet.DispatcherServlet.CONTEXT"; |
There was a problem hiding this comment.
Additionally, it doesn't seem to me that what is being retrieved here is the dispatcher servlet's context, per se. The point of Rob's suggestion is to decouple the application context from its source. Thus, a better name might be APPLICATION_CONTEXT_ATTRIBUTE.
| } | ||
|
|
||
| private ApplicationContext getApplicationContext() { | ||
| Object dispatcherContext = getRequest().getAttribute(DISPATCHER_SERVLET_CONTEXT_ATTRIBUTE); |
There was a problem hiding this comment.
At this point in the code, we aren't sure what it is, so perhaps value is a better variable name.
|
|
||
| private ApplicationContext getApplicationContext() { | ||
| Object dispatcherContext = getRequest().getAttribute(DISPATCHER_SERVLET_CONTEXT_ATTRIBUTE); | ||
| if (dispatcherContext instanceof ApplicationContext applicationContext) { |
There was a problem hiding this comment.
Instead of silently falling back, let's please error if the attribute is being misused:
if (value == null) {
return SecurityWebApplicationContextUtils.findRequiredWebApplicationContext(getServletContext());
}
if (value instanceof ApplicationContext context) {
return context;
}
throw new IllegalArgumentException("WebAttributes.APPLICATION_CONTEXT_ATTRIBUTE value must be of type ApplicationContext, found type " + value.getClass());The reason for this is to alert the application developer to the misconfiguration as early as possible.
|
|
||
| @Test | ||
| @SuppressWarnings("rawtypes") | ||
| public void expressionFromDispatcherContextWhenRootContextPresent() throws IOException { |
There was a problem hiding this comment.
Please remove the dispatcher-specific language in this test.
| this.tag.setAccess("permitAll"); | ||
| assertThat(this.tag.authorize()).isTrue(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Please add a test to confirm an error if the attribute is not of type ApplicationContext.
| given(dispatcher.getBeanNamesForType(SecurityContextHolderStrategy.class)).willReturn(new String[0]); | ||
| this.request.setAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", dispatcher); | ||
| this.tag.setAccess("permitAll"); | ||
| assertThat(this.tag.authorize()).isTrue(); |
There was a problem hiding this comment.
Please verify here that the mocked context was the one that was used.
|
|
||
| @Test | ||
| @SuppressWarnings("rawtypes") | ||
| public void expressionFromDispatcherContextWhenRootContextPresent() throws IOException { |
There was a problem hiding this comment.
The name here seems to indicate that we would only expect looking up the "dispatcher context" when the "root context" is present. However, the logic you are adding is about using the WebAttribute-based Application Context when one is specified. Will you please adjust the name?
Closes gh-8843
When both root and child web application contexts are present, JSP authorize
tags should resolve security beans from the DispatcherServlet context used for
the current request.
Previously,
AbstractAuthorizeTagalways resolved beans fromfindRequiredWebApplicationContext(servletContext), which prefers the rootcontext. If security beans were defined only in the child context, this could
cause failures like missing
WebSecurityExpressionHandler.Changes include:
context attribute when available
SecurityWebApplicationContextUtils.findRequiredWebApplicationContextwhen no dispatcher context is present
<sec:authorize>expression evaluation succeeds