Spring 5: How to load static resources (css, js, images) - spring

I am upgrading a project from Spring 4 to spring 5 but loading static resources is not working.
I have my resources in
src/main/resources/static/js,
src/main/resources/static/css and
src/main/resources/static/images
I add a ResourceHandler in WebConfig as follows
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.job.controllers"})
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
// more code here
}
My security configuration to allow access to the static resources is as follows
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login**", "/static/**").permitAll()
}
}
When i access http://localhost:8080/static/css/file.css
I get the error 405 Request method 'GET' not supported
The problem seems not to be in the security config as it doesn't redirect me to the login page. If I try a none public URL like http://localhost:8080/some-place/css/file.css i get redirected to the login page.
The problem seems to be in the ResourceHandler.
My dependencies are:
spring-framework - 5.0.2.RELEASE and spring-security-5.0.0.RELEASE
None of the answers in the other questions work for me.
other-question
Thanks

I realised that when I commented out the #ComponentScan(basePackages = {"com.job.controllers"}) line on WebConfig class, the static resources would load.
This meant that that the problem was in one of my controllers.
One controller method was mapped #RequestMapping(params = "settings/view", method = RequestMethod.POST)
That mapping showed up as INFO Mapped "{[],methods=[POST],params=[settings/view]}" onto ..... in the startup logs
This was an incorrect mapping and it was stopping the static resources from loading.
When I corrected 'params' to 'value' like this => #RequestMapping(value = "settings/view", method = RequestMethod.POST) the static resources loaded.
Thanks

Related

mockmvc unable to retrieve headers set by WebSecurityConfigurerAdapter

I created a commons library with the intent of injecting headers into the response of every API call. I updated the WebSecurityConfigurerAdaptor and wrote a mockmvc test case to test/assert those headers. However I observed that mockmvc is unable to find/assert those headers in the test even though WebSecurityConfigurerAdaptor injects those headers. Appreciate if you can share your perspective upon any issues you see with this approach.
Below is the WebSecurityConfigurerAdapter snippet:
#Slf4j
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SoaWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Getter
#Setter
private RestTemplateBuilder restTemplateBuilder;
#Override
protected void configure(final HttpSecurity http) throws Exception {
// Disable caching
http.headers().cacheControl();
// default deny framing/embedding
http.headers().frameOptions().deny();
headerConfigurer(http.headers());
}
protected void headerConfigurer(HeadersConfigurer<HttpSecurity> headersConfigurer) {
log.info("SOACustomWebSecurityConfig: header config invoked");
headersConfigurer.addHeaderWriter(
// (HeaderWriter) new StaticHeadersWriter(Arrays.asList(new Header("Access-control-Allow-Origin", "*"),
// new Header("strict-transport-security", "max-age=31536000; includeSubdomains"))));
(HeaderWriter) new StaticHeadersWriter("strict-transport-security",
"max-age=31536000; includeSubdomains"));
}
Below is the corresponding test case:
private void testHeadersPresence(String resourceURl, String origin) throws Exception {
mvc.perform(options(resourceURl).header("Access-Control-Request-Method", "GET").header("Origin", origin))
.andExpect(header().string("strict-transport-security", "max-age=31536000; includeSubdomains"));
}
The test case fails with the error:
Expected "max-age=31536000; includeSubdomains" but was [null]
Note: the change is being made in a common library (a separate repo) which is included in multiple spring boot services (that offers APIs)
Any insight is much appreciated. Thank you

Spring Security Method Without Login Form

I want to just secure the method but not the end point( API) with #Secured. In the over ride method that extends GlobalMethodSecurityConfiguration i will have way to call the some dependent service if the user is allowed depending the on input passed in #Secured Annotation.
for example
#Secured("abc")
public void secureMethod(){
system.out.println("You are allowed)
}
The interceptor (that extends GlobalMethodSecurityConfiguration) method will check if the input to #Secured method has input as abc or something and then return access_denied to this method only. The input to method will be passed by calling service and can be injected at run time.
How i can do that w/o having login screen.
I'm not sure I fully got your question, but to disable the form-login including login/logout screens you would do this:
#Configuration
#EnableWebSecurity
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity security) throws Exception
{
security.formLogin().disable();
}
}
Note: As you are using GlobalMethodSecurityConfiguration , you can try and nest this class INSIDE it.
So:
#Configuration
#EnableGlobalMethodSecurity
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
// do whatever is needed here
#Configuration
public static class WebSecurityConfig extends
WebSecurityConfigurerAdapter { // nesting
#Override
protected void configure(HttpSecurity security) throws Exception
{
security.formLogin().disable();
}
}
}

Spring Boot url mappings order for controllers and static pages

I have a Spring Boot web application which is meant to serve both static and controller based (ModelAndView) pages. Problem is that a controller can serve something like /{string} and a static page must be served with /test.
The problem is that the controller mapping takes precedence, and I need to avoid that. If the user hits /test, he must be forwarded to the test.html static page.
I tried to use the order property of ViewControllerRegistry in this way, with no success:
#Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/test").setViewName("forward:/test.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE); // but I tried with 0 and -1 as well: annotated controllers should have order equals to 0
}
}
This is my SpringBootApplication class:
#SpringBootApplication
public class VipApplication {
public static void main(String[] args) {
SpringApplication.run(VipApplication.class, args);
}
}
And this is the controller code:
#Controller
public class VipController {
#RequestMapping(value = "/{string}")
public ModelAndView vip(#PathVariable("string") String string) {
ModelAndView mv = new ModelAndView("mypage");
return mv;
}
}
How can I reorder the mappings to make sure static pages are considered before annotated controllers?
(I'm not sure, but) I suggest to override WebMvcConfigurerAdapter.addResourceHandlers() method and configure order of resource handler by invoking ResourceHandlerRegistry.setOrder()

Spring MVC TrailingSlash matching

I am using Spring MVC 4.1, and this is the core config:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {""})
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
configurer.setUseTrailingSlashMatch(false);
}
....
}
#Controller
#RequestMapping("/api/deps")
public class DepartmentCtrl {
#RequestMapping(value = "", method = RequestMethod.GET)
public Result index() {
return ...;
}
}
While when I open this the url:
/context/api/deps
I will get the result as expected, however once I will get a 404 once I visit the link:
/context/api/deps/
As shown, I have config the PathMatchConfigurer by setUseTrailingSlashMatch(false) , but it seems that it does not work.
Is there anything wrong in my configuration?
use this:
setUseTrailingSlashMatch(true)
According to javadoc, setUseTrailingSlashMatch determines:
Whether to match to URLs irrespective of the presence of a trailing
slash. If enabled a method mapped to "/users" also matches to
"/users/".
Honestly, there is no need for this piece of configuration, since its enabled by default and you by passing false to it, disabled it.
What happens when you pass "/" in the value attribute of RequestMapping Annotation?

Spring serving static content while having wildcard controller route

My application is build using backbone on frontend and spring framework on backend. It is a single html application. Routes are handled by backbone, so I have a backend route with the next structure:
#RequestMapping(value="/**", method=RequestMethod.GET)
public String Pages()
{
return "index";
}
To point everything to my index.html. The thing is that the static content
files are pointed to this route too, and I don't want this. I've tried to
config WebMvcConfigurerAdapter by overriding addResourceHandler method for
static content, but it doesn't work.
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("/resources/js");
}
}
How can I point every route to my index.html except /js/** and /assets/** ?
Thank you
The first thing is that your controller method that's mapped to /** will be taking priority over any resource requests. You can address this by increasing the precedence of ResourceHandlerRegistry. Add a call to registry.setOrder(Ordered.HIGHEST_PRECEDENCE) in the addResourceHandlers method of StaticResourceConfiguration:
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addResourceHandler("/js/**").addResourceLocations("/resources/js");
}
}
The second thing is that, by default, Spring Boot configures two resource handlers for you by default, one mapped to /** and one mapped to /webjars/**. Due to the change described above, this will now take priority over the method in your controller that's also mapped to /**. To overcome this, you should turn off default resource handling via a setting in application.properties:
spring.resources.addMappings=false

Resources