Search code examples
spring-securityspring-annotations

@PreAuthorize and intercept-url priority


I have

<security:http use-expressions="true">
    <security:intercept-url pattern="/**/*" access="hasRole('ROLE_USER')"/>

in the Spring Security context configuration file and

@PreAuthorize("permitAll")
@RequestMapping("/public")
public String aMethod() {
    // ...
}

in a controller.

What I want is that all the URLs to require authentication except public. Is this possible?


Solution

  • <intercept-url> in XML takes precedence over annotations. <intercept-url> works at URL level and annotations at method level.

    If you are going to use spring security and spring <form-login /> then the approach below would serve you better.

    <intercept-url pattern="/public/**"
                       access="permitAll" />
    
    <intercept-url pattern="/restricted/**"
                       access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN', 'ROLE_SOME')
    
    
    @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SOME')")
    @RequestMapping("/restricted/aMethod")
    public String aMethod() {
        // ...
    }
    

    Anything under restricted can be accessed by three different roles. But specific path restricted/aMethod can be accessed by @PreAuthorize("ROLE_ADMIN") and @PreAuthorize("ROLE_SOME") but NOT by @PreAuthorize("ROLE_USER"). By default all three roles can access but when you mark some path with @PreAuthorize("ROLE_ADMIN") then user with ROLE_ADMIN can access that path.

    If you think about it, @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SOME')") act as narrowed or filtered access from a large set of ROLES to single(or set of roles) ROLE.

    As you would notice, none of /restricted paths are accessible by permitAll. Its preferred to have /static/*.css and others under permitAll.

    HTH