Spring Boot property in @Preauthorize

后端 未结 3 1422
没有蜡笔的小新
没有蜡笔的小新 2021-01-14 08:25

I\'m setting up a Spring Boot (v1.2.6) web project and using Spring Security (v3.2.8). I\'ve found the @PreAuthorize annotation so handy, but I don\'t know if there\'s a way

相关标签:
3条回答
  • 2021-01-14 08:40

    This should work:

    @Value("${mysecurity.permit}")
    private Boolean permit;
    

    Then use:

    @PreAuthorize(permit)
    

    But you need to properly set configuration file, to allow Spring access it. Read here: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

    UPDATE: Did you configure bean for a property placeholder? For example:

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
        <list>
            <value>classpath:com/foo/app.properties</value>
        </list>
        </property>
    </bean>
    
    0 讨论(0)
  • 2021-01-14 08:42

    This maybe a generic way to evaluate expressions which i want to share with you:

    @Component("AuthorizationComponent")
    public final class AuthorizationComponent {
        private final static Logger logger = Logger.getLogger(AuthenticationUtils.class.getName());
    
        private static SpelExpressionParser parser;
        static {
            parser = new SpelExpressionParser();
        }
    
        @Autowired
        private Environment environment;
    
        public boolean evaluateExpression(final String propertyKey) {
            return checkExpression(environment.getProperty(propertyKey));
        }
    
        public static boolean checkExpression(String securityExpression) {
            logger.info("Checking security expression [" + securityExpression + "]...");
    
            SecurityContext securityContext = SecurityContextHolder.getContext();
            Authentication authentication = securityContext.getAuthentication();
    
            Expression exp = parser.parseExpression(securityExpression);
            SecurityExpressionRoot context = new CustomMethodSecurityExpressionRoot(authentication);
            boolean result = exp.getValue(context, Boolean.class);
    
            logger.info("Check result: " + result);
    
            return result;
        }
    }
    

    And in yaml config file you can configure the path and authorization expression, something like that:

    preAuthorize:
      whatever:
        post: hasRole('MY_ROLE') OR hasAuthority('MY_AUTHORITY')
    

    Then you could use it like that over your method:

    @PreAuthorize("@AuthorizationComponent.evaluateExpression('preAuthorize.whatevert.post')")
    @RequestMapping(value = "", method = RequestMethod.POST)
    public ResponseEntity<Void> addQuestion(@Valid @RequestBody BodyRestDTO bodyRestDTO){
        //Code implementation
        return new ResponseEntity<Void>(HttpStatus.CREATED);
    }
    
    0 讨论(0)
  • 2021-01-14 08:59

    The values used in an annotation must be constants. They are evaluated at compile time, and while they may be retained for use at runtime they aren't re-evaluated. So you can use an expression that's evaluated by SpEL, or you can write a helper method that is referenced within the annotation value.

    If you look at the OnExpressionCondition implementation, you will notice that it gets the value passed to the annotation, which in the case linked in your comment would be something like @ConditionalOnExpression("${server.host==localhost} or ${server.port==8080} ") The annotation simply gets the text value, it has no idea what the text represents, it just knows it's a string. It's in the processing of the annotation value within OnExpressionCondition that the String value takes meaning. They take the String value and pass it to a BeanExpressionResolver for resolution.

    So, in your PreAuthorize solution, which based on http://forum.spring.io/forum/spring-projects/security/100708-spel-and-spring-security-3-accessing-bean-reference-in-preauthorize also passes it to an expression processor, you should be able to use spring's expression language to reference any bean property.

    I'm not in a situation to test it currently, but from that thread it seems like you could do something like

    @Component
    public class MyBean {
      @Value("${mysecurity.permit}")
      private Boolean permit;
    
      public boolean isPermitted() { return permit; }
    
      @PreAuthorize( "@myBean.isPermitted()" )
      public blah myMethod() {
        // do stuff
      }
    }
    
    0 讨论(0)
提交回复
热议问题