Spring Security
  1. Spring Security
  2. SEC-1479

Different attitude on diverse webcontainers

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: 3.0.2
    • Fix Version/s: 3.1.0.M1
    • Component/s: None
    • Labels:
      None
    • Environment:
      Windows 7 , maven 2.2 , eclipse 3.5 , maven-jetty-plugin 6.1.24 , tomcat 6.0.20

      Description

      The subsequent snippet may make no sense, but it causes a different attitude with tomcat and the jetty plugin from maven.

      If the following http configuration is used in the applicationContext-security.xml:

      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <beans:beans xmlns="http://www.springframework.org/schema/security"
      3. xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xsi:schemaLocation="http://www.springframework.org/schema/beans
      5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      6. http://www.springframework.org/schema/security
      7. http://www.springframework.org/schema/security/spring-security-3.0.xsd">
        #
      8. <http auto-config='true' use-expressions="true"
      9. disable-url-rewriting="true">
      10. <intercept-url pattern="/" access="ROLE_CARRIER" />
      11. <intercept-url pattern="/restrict/carrier" access="ROLE_CARRIER"/>
      12. <intercept-url pattern="/restrict/customer" access="ROLE_CUSTOMER"/>
      13. <intercept-url pattern="/restrict/distributor" access="ROLE_DISTRIBUTOR"/>
      14. <intercept-url pattern="/index.jsf" filters="none" />
      15. <intercept-url pattern="/failAuth.jsf" filters="none" />
      16. <intercept-url pattern="/**" access="isAuthenticated()" />
      17. <form-login login-page="/index.jsf"
      18. authentication-failure-url="/failAuth.jsf" default-target-url="/successAuth.jsf"
      19. authentication-success-handler-ref="redirectRoledependendStrategy" />
      20. <logout />
      21. </http>

      tomcat serves the website without problems but jetty gives the following exceptions when i try to access localhost:8282/ldapAuth :

      HTTP ERROR 500

      Problem accessing /ldapAuth/. Reason:

      Failed to evaluate expression 'ROLE_CARRIER'

      Caused by:

      java.lang.IllegalArgumentException: Failed to evaluate expression 'ROLE_CARRIER'
      at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:13)
      at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:34)
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:50)
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:203)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
      at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
      at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
      at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
      at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
      at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
      at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
      at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
      at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
      at org.mortbay.jetty.Server.handle(Server.java:326)
      at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
      at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)
      at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
      at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
      at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
      at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
      at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
      Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'ROLE_CARRIER' cannot be found on object of type 'org.springframework.security.web.access.expression.WebSecurityExpressionRoot'
      at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:206)
      at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:71)
      at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
      at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97)
      at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:11)
      ... 44 more

      Caused by:

      org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'ROLE_CARRIER' cannot be found on object of type 'org.springframework.security.web.access.expression.WebSecurityExpressionRoot'
      at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:206)
      at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:71)
      at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
      at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97)
      at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:11)
      at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:34)
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:50)
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:203)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
      at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
      at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
      at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
      at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
      at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
      at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
      at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
      at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
      at org.mortbay.jetty.Server.handle(Server.java:326)
      at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
      at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)
      at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
      at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
      at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
      at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
      at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

      Powered by Jetty://

      If i uncomment the line:

      <intercept-url pattern="/" access="ROLE_CARRIER" />

      the application is successfully accessible on tomcat and jetty.

      The following snippet shows my jetty-configuration in the pom.xml file:

      <plugin>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>maven-jetty-plugin</artifactId>
      <configuration>
      <scanIntervalSeconds>10</scanIntervalSeconds>
      <connectors>
      <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
      <port>8282</port>
      <maxIdleTime>60000</maxIdleTime>
      </connector>
      </connectors>
      </configuration>
      </plugin>

      hth,

      Ramo Karahasan

        Activity

        Hide
        Luke Taylor added a comment -

        You should see the same error in Tomcat. If you can produce a test project which demonstrates that a URL which fails in Jetty is allowed in Tomcat then I will check it, but I don't see any way this can be the case.

        Show
        Luke Taylor added a comment - You should see the same error in Tomcat. If you can produce a test project which demonstrates that a URL which fails in Jetty is allowed in Tomcat then I will check it, but I don't see any way this can be the case.
        Hide
        Ramo Karahasan added a comment -

        Hi Luke,

        i've created to examples "testApp" and "testApp2" . The version "testApp" includes the configuration: <intercept-url pattern="/" access="ROLE_CARRIER" /> and works on tomcat 6.0.20 and not on the jetty plugin (the exception showed previously. The "testApp2" version is configured without the <intercept-url pattern="/" access="ROLE_CARRIER" /> line (commented out). Again the tomcat version is 6.0.20 and the jetty-plugin has the version: 6.1.24

        hth, Ramo

        Show
        Ramo Karahasan added a comment - Hi Luke, i've created to examples "testApp" and "testApp2" . The version "testApp" includes the configuration: <intercept-url pattern="/" access="ROLE_CARRIER" /> and works on tomcat 6.0.20 and not on the jetty plugin (the exception showed previously. The "testApp2" version is configured without the <intercept-url pattern="/" access="ROLE_CARRIER" /> line (commented out). Again the tomcat version is 6.0.20 and the jetty-plugin has the version: 6.1.24 hth, Ramo
        Hide
        Ramo Karahasan added a comment -

        The two versions

        Show
        Ramo Karahasan added a comment - The two versions
        Hide
        Luke Taylor added a comment -

        Ok, thanks for the samples. I think I see the problem. It's not a bug (at least not in Spring Security), but down to the way Jetty and Tomcat handle the welcome-file-list, which you have set to your index.xhtml (in testApp). If you remove that you will get the same error in both containers. When you request the root, Tomcat uses the URL "/index.html":

        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Converted URL to lowercase, from: '/index.xhtml'; to: '/index.xhtml'
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /; matched=false
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/carrier; matched=false
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/customer; matched=false
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/distributor; matched=false
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /index.jsf; matched=false
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /**; matched=true
        [DEBUG,FilterSecurityInterceptor,http-8080-1] Secure object: FilterInvocation: URL

        Whereas Jetty uses the URL "/":

        DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,17066018@qtp-26991461-0] Converted URL to lowercase, from: '/'; to: '/'
        [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,17066018@qtp-26991461-0] Candidate is: '/'; pattern is /; matched=true
        [DEBUG,FilterSecurityInterceptor,17066018@qtp-26991461-0] Secure object: FilterInvocation: URL: /; Attributes: [ROLE_CARRIER]

        So tomcat doesn't attempt to evaluate the invalid expression "ROLE_CARRIER"

        I'm not sure which is correct, or if the servlet spec actually defines what it should be, but it's obviously something you'll need to tak account of if you're using different containers.

        Show
        Luke Taylor added a comment - Ok, thanks for the samples. I think I see the problem. It's not a bug (at least not in Spring Security), but down to the way Jetty and Tomcat handle the welcome-file-list, which you have set to your index.xhtml (in testApp). If you remove that you will get the same error in both containers. When you request the root, Tomcat uses the URL "/index.html": [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Converted URL to lowercase, from: '/index.xhtml'; to: '/index.xhtml' [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /; matched=false [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/carrier; matched=false [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/customer; matched=false [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /restrict/distributor; matched=false [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /index.jsf; matched=false [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,http-8080-1] Candidate is: '/index.xhtml'; pattern is /**; matched=true [DEBUG,FilterSecurityInterceptor,http-8080-1] Secure object: FilterInvocation: URL Whereas Jetty uses the URL "/": DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,17066018@qtp-26991461-0] Converted URL to lowercase, from: '/'; to: '/' [DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource,17066018@qtp-26991461-0] Candidate is: '/'; pattern is /; matched=true [DEBUG,FilterSecurityInterceptor,17066018@qtp-26991461-0] Secure object: FilterInvocation: URL: /; Attributes: [ROLE_CARRIER] So tomcat doesn't attempt to evaluate the invalid expression "ROLE_CARRIER" I'm not sure which is correct, or if the servlet spec actually defines what it should be, but it's obviously something you'll need to tak account of if you're using different containers.
        Hide
        Luke Taylor added a comment -

        I've added some extra docs on how the request is matched when using ant patterns - i.e. the servletPath + pathInfo is used, but it's not really something that can be regarded as a bug.

        Show
        Luke Taylor added a comment - I've added some extra docs on how the request is matched when using ant patterns - i.e. the servletPath + pathInfo is used, but it's not really something that can be regarded as a bug.

          People

          • Assignee:
            Luke Taylor
            Reporter:
            Ramo Karahasan
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: