Announcement Announcement Module
Collapse
No announcement yet.
SpEL and Spring Security 3: accessing bean reference in @PreAuthorize Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SpEL and Spring Security 3: accessing bean reference in @PreAuthorize

    Hi,
    I'm trying to access a bean reference in a @PreAuthorize annotation as follows:

    @PreAuthorize("#{ @testBean.getTestBoolean()}")
    public String testSpEL() {
    ....
    }

    I have a test bean configured as follows:

    @Component(value="testBean")
    public class TestBean {
    public boolean getTestValue() {
    return true;
    }
    }

    When I try to access the testSpEL() method however, I'm confronted with the following exception:

    Caused by: org.springframework.expression.spel.SpelParseExcep tion: EL1043Epos 1): Unexpected token. Expected 'identifier' but was 'lcurly({)'
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.raiseInternalException(Int ernalSpelExpressionParser.java:814)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatToken(InternalSpelExpre ssionParser.java:744)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.maybeEatFunctionOrVar(Inte rnalSpelExpressionParser.java:373)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatStartNode(InternalSpelE xpressionParser.java:452)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatPrimaryExpression(Inter nalSpelExpressionParser.java:300)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatUnaryExpression(Interna lSpelExpressionParser.java:293)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatPowerExpression(Interna lSpelExpressionParser.java:269)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatProductExpression(Inter nalSpelExpressionParser.java:250)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatSumExpression(InternalS pelExpressionParser.java:233)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatRelationalExpression(In ternalSpelExpressionParser.java:195)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatLogicalAndExpression(In ternalSpelExpressionParser.java:183)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatLogicalOrExpression(Int ernalSpelExpressionParser.java:171)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.eatExpression(InternalSpel ExpressionParser.java:135)
    at org.springframework.expression.spel.standard.Inter nalSpelExpressionParser.doParseExpression(Internal SpelExpressionParser.java:116)


    I have thoroughly done my research but I can't find anywhere what I need to change in my configuration to get this to work. Any pointers?

    Thanks!

    Kind regards, Jonck

    P.S. I'm using Spring 3.0.5. The following seems to indicate this type of functionality should work:

    https://jira.springsource.org/browse/SPR-7173

  • #2
    Try just using "testBean.getTestBoolean()" (without the #{} or the @).

    Spring Security doesn't register any BeanResolvers with the EvaluationContext, but will resolve the bean names directly as properties against the ApplicationContext.

    Comment


    • #3
      This causes a different exception:

      Caused by: org.springframework.expression.spel.SpelEvaluation Exception: EL1008Epos 0): Field or property 'testBean' cannot be found on object of type 'org.springframework.security.access.expression.me thod.MethodSecurityExpressionRoot'
      at org.springframework.expression.spel.ast.PropertyOr FieldReference.readProperty(PropertyOrFieldReferen ce.java:207)
      at org.springframework.expression.spel.ast.PropertyOr FieldReference.getValueInternal(PropertyOrFieldRef erence.java:71)
      at org.springframework.expression.spel.ast.CompoundEx pression.getValueInternal(CompoundExpression.java: 52)
      at org.springframework.expression.spel.ast.SpelNodeIm pl.getTypedValue(SpelNodeImpl.java:102)
      at org.springframework.expression.spel.standard.SpelE xpression.getValue(SpelExpression.java:97)
      at org.springframework.security.access.expression.Exp ressionUtils.evaluateAsBoolean(ExpressionUtils.jav a:11)

      Comment


      • #4
        Sorry, my mistake. This is only available in the 3.1 codebase:

        https://jira.springsource.org/browse/SEC-1294

        We should probably look at supporting the standard Spring syntax instead.

        Comment


        • #5
          I have upgraded to Spring Security 3.1.0.RC1 and I can confirm that the syntax "testBean.getTestBoolean()" does indeed work now.

          Thanks for your help!
          Last edited by venercogo; Apr 22nd, 2011, 05:34 AM.

          Comment


          • #6
            I've changed things to use the Spring '@' syntax and BeanResolver. So the next release will support "@testBean.getTestBoolean()" instead of the plain property name. See SEC-1723.

            Comment


            • #7
              Shouldn't this then be "#{ @testBean.getTestBoolean()}" if you want to be compliant with standard SpEL syntax?

              Comment


              • #8
                There's no need for delimiters since there is no need to differentiate between expressions and non-expressions, as there is when using them in an application context, for example.

                The expression is passed directly to the SpelExpressionParser, so the expression evaluation is entirely done by Spring.

                Comment


                • #9
                  That makes sense, thanks for explaining!

                  Comment


                  • #10
                    I have written a blog post regarding this subject, you can find it here:

                    http://blog.42.nl/articles/spring-se...ty-annotations

                    Comment


                    • #11
                      I have problem with @PreAuthorize and accessing bean in expression. Running Spring Security version is 3.1.0RC2.
                      Code:
                      INFO  [SpringSecurityCoreVersion:29] : You are running with Spring Security Core 3.1.0.RC2
                      INFO  [SecurityNamespaceHandler:57] : Spring Security 'config' module version is 3.1.0.RC2
                      applicationContext.xml:
                      Code:
                      <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" />
                      Controller code:
                      Code:
                      @Controller
                      class TestController {
                      
                      	public boolean isOk() {
                      		return true;
                      	}
                      	
                      	@PreAuthorize("testController.isOk()")
                      	@RequestMapping("/test")
                      	public String testPage() {
                      		return "test";
                      	}
                      
                      }
                      I get error:
                      Code:
                      java.lang.IllegalArgumentException: Failed to evaluate expression 'testController.isOk()'
                      ...
                      Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'testController' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot'
                      	at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:207)
                      	at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:71)
                      	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:52)
                      	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)
                      	... 79 more
                      Anybody knows what is wrong with that ?
                      Last edited by marioosh; Sep 16th, 2011, 04:15 AM.

                      Comment


                      • #12
                        Hi,

                        As Luke Taylor wrote, the syntax has been changed slightly in the new release.

                        "I've changed things to use the Spring '@' syntax and BeanResolver. So the next release will support "@testBean.getTestBoolean()" instead of the plain property name. See SEC-1723."

                        Try changing your syntax to match what Luke wrote.

                        Kind regards, Jonck

                        Comment


                        • #13
                          Doubt anyone is watching this thread anymore, but I created a small workaround to add support in Spring Security 3.0.x.

                          For anyone stuck on Spring Security 3.0.x I have a somewhat simple workaround. Add this class in your application-securityContext.xml (or whatever):

                          https://gist.github.com/3340059

                          It injects a BeanFactoryResolver into the Spring Security code, which is all the Spring Security 3.1.x fix has. Support for the syntax is already in 3.0.x. It allows you to use the syntax from 3.1.x, ala:

                          @PreAuthorize("@controller.theProperty")

                          Comment

                          Working...
                          X