Path Variables in Web Security Expressions and set /users/{userId:\\d+}

896 Views Asked by At
spring security 4.1.3.RELEASE intercept-url request-matcher="mvc"

I try to use spring-security.xml to config my web security with request-matche="mvc", but the pattern "/users/{userId:id}" dosen't work.

My config just look like the following code:

<http entry-point-ref="myAuthenticationEntryPoint" auto-config="true" use-expressions="true" create-session="stateless" request-matcher="mvc" 
      access-decision-manager-ref="myAccessDecisionManager">
    <intercept-url pattern="/users/{userId:\\d+}" method="GET" access="@webSecurity.isMe(authentication, #userId) or hasAnyRole('ADMIN')"/>
    <intercept-url pattern="/users/management" method="GET" access="hasAnyRole('ADMIN')"/>
</http>

I expecte that the request for /users/12345 will match the pattern /users/{userId:\d+} which will match 12345 to the userId, and the request for /users/management will match the pattern /users/management. However, in fact, the pattern /users/{userId:\d+} dosen't work, it never match the request /users/12345. and if I change the setting to the following code:

<http entry-point-ref="myAuthenticationEntryPoint" auto-config="true" use-expressions="true" create-session="stateless" request-matcher="mvc" 
      access-decision-manager-ref="myAccessDecisionManager">
    <intercept-url pattern="/users/{userId}" method="GET" access="@webSecurity.isMe(authentication, #userId) or hasAnyRole('ADMIN')"/>
    <intercept-url pattern="/users/management" method="GET" access="hasAnyRole('ADMIN')"/>
</http>

Remove the :\d+ from /users/{userId:\d+}, it will match the request for /users/12345. But it will match the request for /users/management as well, which makes the value of userId equals to unexpected "management". I have try ant-matcher and regex-matcher, and I can't find the userId in a perfect solution.

1

There are 1 best solutions below

0
On

I have solved the problem by myself. It's a stupid mistake. To solve the problem, I just need to replace /users/{userId:\\d+} with /users/{userId:\d+} or /users/{userId:[0-9]+} and use AntPathMatcher instead of using MvcPathMatcher. Configuring the security with spring-security.xml is defferent with using javaConfig or using annotation. In javaConfig or annotation @RequestMapping, the content in "" is String Object, so we need an annother \ to escape the \d+. But in xml, it's unnecessary. If using \\d+ here, spring security will append it to \\\\d+, which will never match number type string. I find this solution when I set a breakpoint in org.springframework.util.AntPathMatcher.matchStrings(String str, Map<String, String> uriTemplateVariables) and watch the request.