Serving static resources in spring security - Allow access to all files in '/resources/public'

ConsultingEasy picture ConsultingEasy · Mar 28, 2018 · Viewed 8k times · Source

I can serve static resources perfectly fine with this setup however I have to define on a file by file basis the files which are allowed to be served.

My current use case is anything located in the /resources/public/ directory should have allowed access by clients.

i've tried the one liner /resources/public/** and /public/** that still doesn't allow access to all public resources i get 403's. So in my http configure i've started defining file extensions that are permitted, but i don't like that approach as there are lots of different extensions in my webapp.

My question is how can i allow access to all files in /resources/public/ without having to define ant matchers for each file extension or am i just being petty?

Spring WebSecurityConfigurerAdapter - edited as per jmw5598's answer.

    @Override
    public void configure(WebSecurity web) throws Exception {
           web
            .ignoring()
            .antMatchers("/resources/**");
    }


    @Override
    protected void configure(HttpSecurity http) {

            http
                .authorizeRequests()
                        .authorizeRequests()
                .antMatchers(
                    "/public/**",
                    "/.svg", "/.ico", "/.eot", "/.woff2",
                    "/.ttf", "/.woff", "/.html", "/.js",
                    "/.map", "/*.bundle.*",
                    "/index.html", "/", "/home", "/dashboard")
                .permitAll()
                .anyRequest().authenticated();
    }

Controller for serving web app:

@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@Controller
public class AngularWebAppController {

    @GetMapping(value = "/{path:[^\\.]*}")
    public String redirect() {
        return "forward:/";
    }

}

My directory structure in /resources

enter image description here

  • Added as requested by dur's comment. enter image description here

Answer

0gam picture 0gam · Mar 29, 2018

You want to request separator resource or URL handler mapping. this is easy in Spring.

Servelet-context

<!-- Handles HTTP GET requests for /resources/** by efficiently serving 
    up static resources in the ${webappRoot}/resources directory -->

<resources mapping="/resources/**" location="/resources/" />

and

<default-servlet-handler />

This tag allows for mapping the DispatcherServlet to "/" (thus overriding the mapping of the container's default Servlet), while still allowing static resource requests to be handled by the container's default Servlet [...]

enter link description here


Maybe you useful this spring security content.

CustomWebSecurityConfigurerAdapter

Our HelloWebSecurityConfiguration sample, demonstrates that Spring Security Java configuration can provide some very nice defaults for us. Let’s take a look at some basic customization.

@EnableWebSecurity
@Configuration
public class CustomWebSecurityConfigurerAdapter extends
   WebSecurityConfigurerAdapter {
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) {
    auth
      .inMemoryAuthentication()
        .withUser("user")  // #1
          .password("password")
          .roles("USER")
          .and()
        .withUser("admin") // #2
          .password("password")
          .roles("ADMIN","USER");
  }

  @Override
  public void configure(WebSecurity web) throws Exception {
    web
      .ignoring()
         .antMatchers("/resources/**"); // #3
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeUrls()
        .antMatchers("/signup","/about").permitAll() // #4
        .antMatchers("/admin/**").hasRole("ADMIN") // #6
        .anyRequest().authenticated() // 7
        .and()
    .formLogin()  // #8
        .loginUrl("/login") // #9
        .permitAll(); // #5
  }
}

Assuming that we adjust AbstractAnnotationConfigDispatcherServletInitializer to load our new configuration, our CustomWebSecurityConfigurerAdapter will do the following:

  • Allow in memory authentication with a user named “user”
  • Allow in memory authentication with an administrative user named “admin”
  • Ignore any request that starts with “/resources/”. This is similar to configuring http@security=none when using the XML namespace configuration.
  • Allow anyone (including unauthenticated users) to access to the URLs “/signup” and “/about”
  • Allow anyone (including unauthenticated users) to access to the URLs “/login” and “/login?error”. The permitAll() in this case means, allow access to any URL that formLogin() uses.
  • Any URL that starts with “/admin/” must be an administrative user. For our example, that would be the user “admin”.
  • All remaining URLs require that the user be successfully authenticated
  • Setup form based authentication using the Java configuration defaults. Authentication is performed when a POST is submitted to the URL “/login” with the parameters “username” and “password”.
  • Explicitly state the login page, which means the developer is required to render the login page when GET /login is requested.

For those that are familiar with the XML based configuration, the configuration above is very similar to the following XML configuration:

<http security="none" pattern="/resources/**"/>
<http use-expressions="true">
  <intercept-url pattern="/logout" access="permitAll"/>
  <intercept-url pattern="/login" access="permitAll"/>
  <intercept-url pattern="/signup" access="permitAll"/>
  <intercept-url pattern="/about" access="permitAll"/>
  <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
  <logout
      logout-success-url="/login?logout"
      logout-url="/logout"
  />
  <form-login
      authentication-failure-url="/login?error"
      login-page="/login"
      login-processing-url="/login"
      password-parameter="password"
      username-parameter="username"
  />
</http>
<authentication-manager>
  <authentication-provider>
    <user-service>
      <user name="user" 
          password="password" 
          authorities="ROLE_USER"/>
      <user name="admin" 
          password="password" 
          authorities="ROLE_USER,ROLE_ADMIN"/>
    </user-service>
  </authentication-provider>
</authentication-manager>

Similarities to the XML Namespace

After looking at our slightly more complicated example, you might be able to find some similarities between the XML namespace and the Java configuration. Here are some of the more useful points:

  • HttpSecurity is quite similar to the http namespace element. It allows configuring web based security for a certain selection (in this case all) requests.
  • WebSecurity is quite similar to any Security namespace elements that are for the web and that do not require a parent (i.e. security=none, debug, etc). It allows configuring things that impact all of web security.
  • WebSecurityConfigurerAdapter is a convenience class that allows customization to both WebSecurity and HttpSecurity. We can extend WebSecurityConfigurerAdapter multiple times (in distinct objects) to replicate the behavior of having multiple http elements.
  • By formatting our Java configuration code it is much easier to read. It can be read similar to the XML namespace equivalent where “and()” represents optionally closing an XML element.

Spring Security Java Config Preview