1

Spring Security 3.2.0.RC2

Given:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
        .authorizeRequests()
            .antMatchers("/restricted/**").hasRole("admin")
            .anyRequest().authenticated()

        // etc
        ;
 }

A user without the admin role trying to access /myapp/restricted/foo.request correctly receives an HTTP 403.

However, given:

@Controller
public class FooController {
    @RequestMapping("/bar.request")
    public String bar() {
        return "forward:/restricted/foo.request";
    }
}

If the user accesses /myapp/bar.request, the user is forwarded to the restricted /myapp/restricted/foo.request. How can this be blocked without explicitly blocking "/bar.request"?

Paul Croarkin
  • 14,496
  • 14
  • 79
  • 118

2 Answers2

7

@kungfuters is correct that the first step is ensuring the Filter is intercepting that request in the first place. To do so with a web.xml you would use the following:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher> <!-- Include FORWARD here -->
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

To do so with Java Configuration you would use the following:

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    protected  EnumSet<DispatcherType> getSecurityDispatcherTypes() {
        return return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC, DispatcherType.FORWARD);
    }

}

The last piece is that the FilterSecurityInterceptor (the piece that ensures URLs are protected) by default will only intercept the REQUEST and not additional dispatches (i.e. forwards). This is done because it is quite rare to protect the URLs that are forwarded to (typically you would protect the URL that does the forwarding). To enable that you need to use the following with xml configuration you need to use http@once-per-request=true:

<http once-per-request="true">
   <!-- ... -->
</http>

Similarly, there is a oncePerRequest property within Java Configuration that can be used. For example:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
        .authorizeRequests()
            .filterSecurityInterceptorOncePerRequest(false)
            // make sure to grant access to any login page you are forwarding to
            .antMatchers("/restricted/login").permitAll()
            .antMatchers("/restricted/**").hasRole("admin")
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .permitAll()
        // etc
        ;
}
Rob Winch
  • 21,440
  • 2
  • 59
  • 76
  • configure `once-per-request="false"` to execute filters again for "forwarded requests", this answer saved my day! – Roy Ling Jul 27 '17 at 08:44
3

If you are using web.xml to configure your filter, try this:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher> <!-- Include FORWARD here -->
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

...or use the Servlet3 Java-based Config equivalent, which is to extend AbstractSecurityWebApplicationInitializer and override the getSecurityDispatcherTypes() method:

public class YourSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    protected  EnumSet<DispatcherType> getSecurityDispatcherTypes() {
        // Return dispatcher types here, in your case you'll want the defaults, 
        // which are DispatcherType.REQUEST and DispatcherType.ERROR
        // ...as well as the one you need for your use case: DispatcherType.FORWARD
    }

}

I typed that here, so hopefully there are no errors. Should get you going, though.

MattSenter
  • 3,060
  • 18
  • 18
  • What version of Spring Security are you using? I've tried both Java Config and web.xml configurations and in 3.2.0.RC, neither works on FORWARD. – Paul Croarkin Nov 13 '13 at 15:45
  • 3.2.0.RC2, but that's odd. This isn't really a Spring-specific issue...it's really just a base Java Servlet Filter configuration. Although obviously you're having to use a Spring class to enable the FORWARD dispatcher type on the Filter. Overriding that method is definitely how it's SUPPOSED to work...if I get a chance I will set up a test environment. – MattSenter Nov 13 '13 at 16:38