我试图实现资源版本控制,使我的静态文件(js和css)由spring的VersionResourceResolver根据Spring's documentation动态版本化 我有我的xml配置:
<mvc:resources mapping="/css/**" location="/css/">
<mvc:resource-chain resource-cache="true" auto-registration="true">
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>
<mvc:resources mapping="/js/**" location="/js/">
<mvc:resource-chain resource-cache="true" auto-registration="true">
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>
在我的web.xml中添加ResourceUrlEncodingFilter时效果很好:
<filter>
<filter-name>resourceUrlEncodingFilter</filter-name>
<filter-class>org.springframework.web.servlet.resource.ResourceUrlEncodingFilter</filter-class>
<init-param>
<param-name>addMappingForUrlPatterns</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>resourceUrlEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
唯一的一点是,当textSecurityFilterChain出现在web.xml上时,它不起作用,如果我对springSecurityFilterChain的行进行注释,过滤器可以完美地工作,根据this post似乎是在4.1.2版本上解决的bug,如指定的here
那个静态文件的url只是被完全忽略了,当安全性没有启用时,ResourceUrlEncodingFilter只调用它的encodeURL()方法,如何解决它的任何想法?我认为该bug的解决方案已添加到4.1.5.RELEASE版本中。
答案 0 :(得分:2)
只有在未启用安全性时才会调用过滤器(ResourceUrlEncodingFilter)这一事实让我相信Spring Security正在拦截对静态资源的调用(并且不允许它们传递给过滤器)。请验证您的Spring Security配置是否允许通过静态资源调用。
假设你的css&#39;和&#39; js&#39;文件夹在src / main / resources下,你可以这样做:
(JavaConfig)
class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
...
}
(XML配置)
...
<http security="none" pattern="/resources/**"/>
...
答案 1 :(得分:1)
我有同样的问题。 看起来它与HttpSessionSecurityContextRepository $ Servlet3SaveToSessionRequestWrapper相关,Spring安全性将其用作HttpServletRequest的包装器。它取代了ResourceUrlEncodingFilter所需的一些关键方法实现。
现在我通过创建两个过滤器来使用丑陋的黑客:
首先这样做(应该是过滤器链中的第一个):
static final String INITIAL_REQUEST_ATTR = "INITIAL_REQUEST";
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(INITIAL_REQUEST_ATTR, request);
filterChain.doFilter(request, response);
}
第二个是基本上被黑客攻击的ResourceUrlEncodingFilter副本 映射到我的调度程序servlet(用它替换标准)
public class ResourceUrlEncodingFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
throw new ServletException("ResourceUrlEncodingFilter just supports HTTP requests");
}
HttpServletRequest initialRequest =
(HttpServletRequest) request.getAttribute(InitialRequestStoreFilter.INITIAL_REQUEST_ATTR);
if (initialRequest == null) {
throw new IllegalStateException("Initial request is not stored");
}
filterChain.doFilter(request,
new ResourceUrlEncodingResponseWrapper(initialRequest, (HttpServletResponse) response));
}
private static class ResourceUrlEncodingResponseWrapper extends HttpServletResponseWrapper {
private final HttpServletRequest initialRequest;
/* Cache the index and prefix of the path within the DispatcherServlet mapping */
private Integer indexLookupPath;
private String prefixLookupPath;
ResourceUrlEncodingResponseWrapper(HttpServletRequest initialRequest, HttpServletResponse wrapped) {
super(wrapped);
this.initialRequest = initialRequest;
}
@Override
public String encodeURL(String url) {
ResourceUrlProvider resourceUrlProvider = getResourceUrlProvider();
if (resourceUrlProvider == null) {
log.debug("Request attribute exposing ResourceUrlProvider not found");
return super.encodeURL(url);
}
initLookupPath(resourceUrlProvider);
if (url.startsWith(this.prefixLookupPath)) {
int suffixIndex = getQueryParamsIndex(url);
String suffix = url.substring(suffixIndex);
String lookupPath = url.substring(this.indexLookupPath, suffixIndex);
lookupPath = resourceUrlProvider.getForLookupPath(lookupPath);
if (lookupPath != null) {
return super.encodeURL(this.prefixLookupPath + lookupPath + suffix);
}
}
return super.encodeURL(url);
}
private ResourceUrlProvider getResourceUrlProvider() {
return (ResourceUrlProvider) this.initialRequest.getAttribute(
ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR);
}
private void initLookupPath(ResourceUrlProvider urlProvider) {
if (this.indexLookupPath == null) {
UrlPathHelper pathHelper = urlProvider.getUrlPathHelper();
String requestUri = pathHelper.getRequestUri(this.initialRequest);
String lookupPath = pathHelper.getLookupPathForRequest(this.initialRequest);
this.indexLookupPath = requestUri.lastIndexOf(lookupPath);
this.prefixLookupPath = requestUri.substring(0, this.indexLookupPath);
if ("/".equals(lookupPath) && !"/".equals(requestUri)) {
String contextPath = pathHelper.getContextPath(this.initialRequest);
if (requestUri.equals(contextPath)) {
this.indexLookupPath = requestUri.length();
this.prefixLookupPath = requestUri;
}
}
}
}
private int getQueryParamsIndex(String url) {
int index = url.indexOf("?");
return (index > 0 ? index : url.length());
}
}
}
这样可行,但根据我的意见,这不是一个好的解决方案。 所以希望它会得到解决,或者有人会提供更好的解决方案