How to parse spring security expressions programma

2019-05-07 05:53发布

How do you parse spring (web) security expressions like hasRole('admin') programmatically (without using tags, annotations or ...)? (reference doc)

I've found Spring: What parser to use to parse security expressions - but I don't know how to find or build the EvaluationContext e.g. inside a spring controller.

Without providing an EvaluationContext gives

org.springframework.expression.spel.SpelEvaluationException: EL1011E:(pos 0): Method call: Attempted to call method hasRole(java.lang.String) on null context object

1条回答
虎瘦雄心在
2楼-- · 2019-05-07 06:23

you need to add several things in order to get this thing working. You have to plug into the Spring's security API. Here's how I did it and it is working fine with Spring 3.2. First as it was stated before you must have similar configuration in your spring-context.xml:

<security:http access-decision-manager-ref="customAccessDecisionManagerBean"> 

<security:http/>

<bean id="customWebSecurityExpressionHandler" 
    class="com.boyan.security.CustomWebSecurityExpressionHandler"/>

<bean id="customAccessDecisionManagerBean" 
    class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                    <property name="expressionHandler" ref="customWebSecurityExpressionHandler" />
                </bean>
            </list>
        </property> 
</bean>

This defines a new expressionHandler to override the default one for the WebExpressionVoter. Then we add this new decision voter to the decision manager. CustomWebSecurityExpressionHandler's purpose it to control the creation of SecurityExpressionRoot. So far so good. The question is why do you need a CustomWebSecurityExpressionRoot and the answer is simple as that - you define your custom security methods there. Having this in mind we can write the following classes:

public class CustomWebSecurityExpressionHandler extends DefaultWebSecurityExpressionHandler {

    @Override
    protected SecurityExpressionOperations createSecurityExpressionRoot(
                Authentication authentication, FilterInvocation fi) {
          CustomWebSecurityExpressionRoot expressionRoot = 
              new CustomWebSecurityExpressionRoot(authentication, delegationEvaluator);

        return expressionRoot;
       }

    }
}

public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot {

    public CustomWebSecurityExpressionRoot(Authentication auth, FilterInvocation fi) {
            super(auth, fi);
    }

    // in here you must define all of the methods you are going to invoke in @PreAuthorize
    // for example if you have an expression with @PreAuthorize('isBoyan(John)')
    // then you must have the following method defined here:
    public  boolean isBoyan(String value) {
        //your logic goes in here
        return "Boyan".equalsIgnoreCase(value);
    }

}

If you want to get a reference to the ExpressionParser you can use the following method AbstractSecurityExpressionHandler.getExpressionParser(). It is accessible through CustomWebSecurityExpressionHandler. Also you can take a look at its API if you want to do something more specific. I hope this answers you question.

查看更多
登录 后发表回答