简体   繁体   中英

Spring Security intercept url appears to be skipped/ignored

I would like to have spring security configured so that one specific resource is locked down to a group, the rest are available to any logged in user. My security.xml looks like this

<http auto-config="true" create-session="stateless" use-expressions="true">
    <intercept-url pattern="/server/**" access="hasRole('ROLE_DEV-USER')" method="POST" requires-channel="https"/>

    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="POST" requires-channel="https"/>
    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="PUT" requires-channel="https"/>
    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="DELETE" requires-channel="https"/>

    <intercept-url pattern="/**" access="permitAll" method="GET" requires-channel="any"/>
    <intercept-url pattern="/**" access="permitAll" method="HEAD" requires-channel="any"/>
    <http-basic />
    <logout />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="admin" password="admin" authorities="ROLE_NOT-DEV-USER" />
            <user name="admin2" password="admin2" authorities="ROLE_DEV-USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

I would expect the only admin to be able to POST to server/enable and server/disable. What I am actually seeing is both admin and admin2 can POST to the server/enable resource. As though the /server/** is ignored and the next more generic intercept-url is taking its place. The start up logs show all lines being loaded

2013-08-21 15:07:42,124  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'hasRole('ROLE_DEV-USER')' for /server/**
2013-08-21 15:07:42,125  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'isFullyAuthenticated()' for /**
2013-08-21 15:07:42,125  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'isFullyAuthenticated()' for /**
2013-08-21 15:07:42,126  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'isFullyAuthenticated()' for /**
2013-08-21 15:07:42,126  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'permitAll' for /**
2013-08-21 15:07:42,127  INFO FilterInvocationSecurityMetadataSourceParser:134 - Creating access control expression attribute 'permitAll' for /**

Currently using spring v3.1.2

Intercept URLs are evaluated in the order they appear. From the docs at http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-web-filters.html

Patterns are always evaluated in the order they are defined. Thus it is important that more specific patterns are defined higher in the list than less specific patterns. This is reflected in our example above, where the more specific /secure/super/ pattern appears higher than the less specific /secure/ pattern. If they were reversed, the /secure/ pattern would always match and the /secure/super/ pattern would never be evaluated.

..so as long as your more specific URL is at the top it should work. It might be worth debugging to see how spring security is evaluating and trying to match your URLs. Sorry, not really an answer, but too big for a comment.

The pattern needs to be expanded to include the url-pattern used to match the servlet

web.xml

<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>
</filter-mapping>
<servlet>
    <servlet-name>restServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-dispatchservlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>restServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

So spring security needs the servlet mapping, plus the request mapping to get to the url and apply the intercept

<http auto-config="true" create-session="stateless" use-expressions="true">
    <intercept-url pattern="/rest/server/**" access="hasRole('ROLE_DEV-USER')" method="POST" requires-channel="https"/>

    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="POST" requires-channel="https"/>
    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="PUT" requires-channel="https"/>
    <intercept-url pattern="/**" access="isFullyAuthenticated()" method="DELETE" requires-channel="https"/>

    <intercept-url pattern="/**" access="permitAll" method="GET" requires-channel="any"/>
    <intercept-url pattern="/**" access="permitAll" method="HEAD" requires-channel="any"/>
    <http-basic />
    <logout />
</http>

Once the missing /rest is added to the pattern it works as expected

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM