Spring security request matcher is not working with regex

Posted by Felipe Cardoso Martins on Stack Overflow See other posts from Stack Overflow or by Felipe Cardoso Martins
Published on 2012-11-21T23:52:16Z Indexed on 2012/11/22 22:59 UTC
Read the original article Hit count: 532

Filed under:
|
|
|

Using Spring MVC + Security I have a business requirement that the users from SEC (Security team) has full access to the application and FRAUD (Anti-fraud team) has only access to the pages that URL not contains the words "block" or "update" with case insensitive.

Bellow, all spring dependencies:

$ mvn dependency:tree | grep spring
[INFO] +- org.springframework:spring-webmvc:jar:3.1.2.RELEASE:compile
[INFO] |  +- org.springframework:spring-asm:jar:3.1.2.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:3.1.2.RELEASE:compile
[INFO] |  +- org.springframework:spring-context:jar:3.1.2.RELEASE:compile
[INFO] |  +- org.springframework:spring-context-support:jar:3.1.2.RELEASE:compile
[INFO] |  \- org.springframework:spring-expression:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-core:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-web:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework.security:spring-security-core:jar:3.1.2.RELEASE:compile
[INFO] |  \- org.springframework:spring-aop:jar:3.0.7.RELEASE:compile
[INFO] +- org.springframework.security:spring-security-web:jar:3.1.2.RELEASE:compile
[INFO] |  +- org.springframework:spring-jdbc:jar:3.0.7.RELEASE:compile
[INFO] |  \- org.springframework:spring-tx:jar:3.0.7.RELEASE:compile
[INFO] +- org.springframework.security:spring-security-config:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework.security:spring-security-acl:jar:3.1.2.RELEASE:compile

Bellow, some examples of mapped URL path from spring log:

Mapped URL path [/index] onto handler 'homeController'
Mapped URL path [/index.*] onto handler 'homeController'
Mapped URL path [/index/] onto handler 'homeController'
Mapped URL path [/cellphone/block] onto handler 'cellphoneController'
Mapped URL path [/cellphone/block.*] onto handler 'cellphoneController'
Mapped URL path [/cellphone/block/] onto handler 'cellphoneController'
Mapped URL path [/cellphone/confirmBlock] onto handler 'cellphoneController'
Mapped URL path [/cellphone/confirmBlock.*] onto handler 'cellphoneController'
Mapped URL path [/cellphone/confirmBlock/] onto handler 'cellphoneController'
Mapped URL path [/user/update] onto handler 'userController'
Mapped URL path [/user/update.*] onto handler 'userController'
Mapped URL path [/user/update/] onto handler 'userController'
Mapped URL path [/user/index] onto handler 'userController'
Mapped URL path [/user/index.*] onto handler 'userController'
Mapped URL path [/user/index/] onto handler 'userController'
Mapped URL path [/search] onto handler 'searchController'
Mapped URL path [/search.*] onto handler 'searchController'
Mapped URL path [/search/] onto handler 'searchController'
Mapped URL path [/doSearch] onto handler 'searchController'
Mapped URL path [/doSearch.*] onto handler 'searchController'
Mapped URL path [/doSearch/] onto handler 'searchController'

Bellow, a test of the regular expressions used in spring-security.xml (I'm not a regex speciality, improvements are welcome =]):

import java.util.Arrays;
import java.util.List;

public class RegexTest {

    public static void main(String[] args) {

        List<String> pathSamples = Arrays.asList(
                "/index",
                "/index.*",
                "/index/",
                "/cellphone/block",
                "/cellphone/block.*",
                "/cellphone/block/",
                "/cellphone/confirmBlock",
                "/cellphone/confirmBlock.*",
                "/cellphone/confirmBlock/",
                "/user/update",
                "/user/update.*",
                "/user/update/",
                "/user/index",
                "/user/index.*",
                "/user/index/",
                "/search",
                "/search.*",
                "/search/",
                "/doSearch",
                "/doSearch.*",
                "/doSearch/");

        for (String pathSample : pathSamples) {
            System.out.println("Path sample: " + pathSample
                    + " - SEC: " + pathSample.matches("^.*$")
                    + " | FRAUD: " + pathSample.matches("^(?!.*(?i)(block|update)).*$"));
        }
    }
}

Bellow, the console result of Java class above:

Path sample: /index - SEC: true | FRAUD: true
Path sample: /index.* - SEC: true | FRAUD: true
Path sample: /index/ - SEC: true | FRAUD: true
Path sample: /cellphone/block - SEC: true | FRAUD: false
Path sample: /cellphone/block.* - SEC: true | FRAUD: false
Path sample: /cellphone/block/ - SEC: true | FRAUD: false
Path sample: /cellphone/confirmBlock - SEC: true | FRAUD: false
Path sample: /cellphone/confirmBlock.* - SEC: true | FRAUD: false
Path sample: /cellphone/confirmBlock/ - SEC: true | FRAUD: false
Path sample: /user/update - SEC: true | FRAUD: false
Path sample: /user/update.* - SEC: true | FRAUD: false
Path sample: /user/update/ - SEC: true | FRAUD: false
Path sample: /user/index - SEC: true | FRAUD: true
Path sample: /user/index.* - SEC: true | FRAUD: true
Path sample: /user/index/ - SEC: true | FRAUD: true
Path sample: /search - SEC: true | FRAUD: true
Path sample: /search.* - SEC: true | FRAUD: true
Path sample: /search/ - SEC: true | FRAUD: true
Path sample: /doSearch - SEC: true | FRAUD: true
Path sample: /doSearch.* - SEC: true | FRAUD: true
Path sample: /doSearch/ - SEC: true | FRAUD: true

Tests

Scenario 1

Bellow, the important part of spring-security.xml:

<security:http entry-point-ref="entryPoint" request-matcher="regex">

    <security:intercept-url pattern="^.*$" access="ROLE_SEC" />
    <security:intercept-url pattern="^(?!.*(?i)(block|update)).*$" access="ROLE_FRAUD" />

    <security:access-denied-handler error-page="/access-denied.html" />

    <security:form-login always-use-default-target="false"
        login-processing-url="/doLogin.html"
        authentication-failure-handler-ref="authFailHandler"
        authentication-success-handler-ref="authSuccessHandler" />
    <security:logout logout-url="/logout.html"
        success-handler-ref="logoutSuccessHandler" />
</security:http>

Behaviour:

  • FRAUD group **can't" access any page
  • SEC group works fine

Scenario 2

NOTE that I only changed the order of intercept-url in spring-security.xml bellow:

<security:http entry-point-ref="entryPoint" request-matcher="regex">

    <security:intercept-url pattern="^(?!.*(?i)(block|update)).*$" access="ROLE_FRAUD" />
    <security:intercept-url pattern="^.*$" access="ROLE_SEC" />

    <security:access-denied-handler error-page="/access-denied.html" />

    <security:form-login always-use-default-target="false"
        login-processing-url="/doLogin.html"
        authentication-failure-handler-ref="authFailHandler"
        authentication-success-handler-ref="authSuccessHandler" />
    <security:logout logout-url="/logout.html"
        success-handler-ref="logoutSuccessHandler" />
</security:http>

Behaviour:

  • SEC group **can't" access any page
  • FRAUD group works fine

Conclusion

I did something wrong or spring-security have a bug.

The problem already was solved in a very bad way, but I need to fix it quickly. Anyone knows some tricks to debug better it without open the frameworks code?

Cheers,

Felipe

© Stack Overflow or respective owner

Related posts about java

Related posts about regex