Resource not found after Spring 4.1.2. Deployment update with JRebel 6.0.0

Spring 4.1.2 (4.0.8 and 3.2.12) contains security patch SPR-12354 that prevents the ResourceHttpRequestHandler (the thing behind <mvc:resources> ) to download files from the resource folder.

On the other hand: JRebel (I use it with my default configuration). And this makes JRebel do some magic to load resources not from the wtp folder, but directly from the "source" folder.

So, after upgrading from Spring from 3.2.11 to 3.2.12 (and another similar application from 4.0.7 to 4.0.8), Springs ResourceHttpRequestHandler no longer delivers resource files that are "supported" by JRebel. Instead, it sends 404. The reason is in that Spring compares the absolute path to the file of the configured resource folder with the absolute path to the file of the file to be delivered. If ResourceHttpRequestHandler understands that the file is outside the configured resource folder, then the URL used to select the file is assumed to be malicious. Therefore, the ResourceHttpRequestHandler and the answer with the resource 404 were not found.

I expect that JRebel can be configured not to "save" js, png and css files, but I do not know how to do this. And here's the question: How do I configure JRebel so that Spring MVC (v 4.0.8) delivers resources using ResourceHttpRequestHandler ?

(I expect that almost every JRebel user will encounter this problem after upgrading to Spring 4.1.2, 4.0.8, or 3.2.12).

(don’t get me wrong, it’s not a question of how to manipulate Spring so that it doesn’t check that the files are outside the settings folder. I looked at the source code and the observed behavior, the authors intended to fix the errors. - This question is about setting up JRebel)

+6
source share
3 answers

The problem is fixed in JRebel (I can not play it with the current JRebel 6.1.1) - I think it is fixed from version 6.0.2 (December 23, 2014)

Fixed a bug due to which Spring ResourceHttpRequestHandler could not serve resources outside of webroot.

(JRebel Changelog https://zeroturnaround.com/software/jrebel/download/changelog/6-x/ )


For those who are interested in how they decided it:

I can only guess because it is strange. Spring 4.1.6 (that is, the version I used for the test) has an org.springframework.web.servlet.resource.PathResourceResolver class has a checkResource(Resource resource, Resource location) method:

 protected boolean checkResource(Resource resource, Resource location) throws IOException { if (isResourceUnderLocation(resource, location)) { return true; } if (getAllowedLocations() != null) { for (Resource current : getAllowedLocations()) { if (isResourceUnderLocation(resource, current)) { return true; } } } return false; } 

The first if : isResourceUnderLocation... is a method that checks whether or not a request to a resource is being accessed outside the configured resource folder

 isResourceUnderLocation(Resource resource, Resource location) { ... resourcePath = ((ServletContextResource) resource).getPath(); locationPath = StringUtils.cleanPath(((ServletContextResource) location).getPath()); ... if (!resourcePath.startsWith(locationPath)) { return false; } ... } 

When I use the debugger to check what is happening while the JRebel is active, something strange happens: when the JVM gets into the line if (isResourceUnderLocation(resource, location)) { , then the isResourceUnderLocation method isResourceUnderLocation not start!

So, I came to the conclusion that JRebel does some manipulation of bytecode to prevent validation (and the whole isResourceUnderLocation method).

+2
source

Thanks for the very good description of the problem!

This Spring change seems to have introduced incompatibility in JRebel. I am from the JRebel team and I will be sure that this will be fixed!

As a workaround, you can use the <exclude> in your rebel.xml <web> element to tell JRebel not to touch these specific files. Here is more detailed information on how to configure it http://manuals.zeroturnaround.com/jrebel/standalone/config.html#exclude

Another easy workaround is to simply remove the <web> element.

+5
source

Based on smartman anwser, I configured rebel.xml as follows:

  <classpath> <dir name="${rebel.workspace.path}/myproject/target/classes"> </dir> <dir name="${rebel.workspace.path}/myproject/target/test-classes"> </dir> </classpath> <web> <link target="/"> <dir name="${rebel.workspace.path}/myproject/src/main/webapp"> <exclude name="resources/**"/> </dir> </link> </web> 

This will exclude all resources, but at least update the views (jsp and tag files). But when I do a lot of frontend development, where I need to change the controller, views and styles at the same time, this configuration is useless, and I have to disable jrebel all together.

+3
source

Source: https://habr.com/ru/post/978112/


All Articles