Доступ к bean-компоненту с помощью SpEL в @PreAuthorize с помощью FullyQualifiedAnnotationBeanNameGenerator

У меня есть контроллер с методом, который имеет логику для проверки разрешения:

      @RestController
@RequestMapping("/example")
public class ExampleController {

    @GetMapping
    @PreAuthorize("@exampleController.hasPermission()")
    public String example() {
        return "hello";
    }

    public boolean hasPermission() {
        return true; // complex logic
    }
}

Как видите, я использую SpEL для вызова этого метода (по имени компонента:exampleController).

Но если я изменю генератор имен компонентов наFullyQualifiedAnnotationBeanNameGenerator:

      @SpringBootApplication(nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class)

теперь имя боба такоеcom.example.demo.ExampleController(проверено в отладчике).

После этого я пытаюсь изменить имя компонента в@PreAuthorized:

      @PreAuthorize("@com.example.demo.ExampleController.hasPermission()")

но это не работает:

      Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception 
  [Request processing failed; nested exception is java.lang.IllegalArgumentException:
  Failed to evaluate expression '@com.example.demo.ExampleController.hasPermission()'] with root cause
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'com' available

Как сослаться на компонент с точками в имени в SpEL? Или как вызвать метод из контроллера по-другому (без использования имени компонента)?

Я знаю, что могу реализовать индивидуальныйAnnotationBeanNameGeneratorбез специальных символов. Но я ожидаю, что генератор имен компонентов Spring совместим с SpEL (языком выражений Spring).

Обновлять

Ответы на это и это тоже не работают (думаю, это работало в конфигурации XML, но не в аннотациях):

      @PreAuthorize("#{@'com.example.demo.ExampleController'.hasPermission()}")
      Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: 
  Failed to parse expression '#{@'com.example.demo.ExampleController'.hasPermission()}'

Обновление 2

Полная трассировка стека (для @dur):

      ERROR [           main] o.s.boot.SpringApplication               : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.example.demo.ExampleController' defined in file [(...)/demo/target/classes/com/example/demo/ExampleController.class]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Failed to parse expression '#{@'com.example.demo.ExampleController'.hasPermission()}'
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.23.jar:5.3.23]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar:5.3.23]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.5.jar:2.7.5]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.5.jar:2.7.5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.5.jar:2.7.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.5.jar:2.7.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.5.jar:2.7.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.5.jar:2.7.5]
    at com.example.demo.DemoApplication.main(DemoApplication.java:11) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: Failed to parse expression '#{@'com.example.demo.ExampleController'.hasPermission()}'
    at org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory.createPreInvocationAttribute(ExpressionBasedAnnotationAttributeFactory.java:59) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource.getAttributes(PrePostAnnotationSecurityMetadataSource.java:80) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource.getAttributes(DelegatingMethodSecurityMetadataSource.java:66) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor$MethodSecurityMetadataSourcePointcut.matches(MethodSecurityMetadataSourceAdvisor.java:127) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:252) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:289) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:321) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:128) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:97) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:78) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:341) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808) ~[spring-beans-5.3.23.jar:5.3.23]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.23.jar:5.3.23]
    ... 15 common frames omitted
Caused by: org.springframework.expression.spel.SpelParseException: Expression [#{@'com.example.demo.ExampleController'.hasPermission()}] @1: EL1043E: Unexpected token. Expected 'identifier' but was 'lcurly({)'
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.internalException(InternalSpelExpressionParser.java:1041) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatToken(InternalSpelExpressionParser.java:923) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.maybeEatFunctionOrVar(InternalSpelExpressionParser.java:421) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatStartNode(InternalSpelExpressionParser.java:510) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPrimaryExpression(InternalSpelExpressionParser.java:350) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatUnaryExpression(InternalSpelExpressionParser.java:344) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPowerIncDecExpression(InternalSpelExpressionParser.java:303) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatProductExpression(InternalSpelExpressionParser.java:281) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatSumExpression(InternalSpelExpressionParser.java:263) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatRelationalExpression(InternalSpelExpressionParser.java:218) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalAndExpression(InternalSpelExpressionParser.java:205) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalOrExpression(InternalSpelExpressionParser.java:192) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatExpression(InternalSpelExpressionParser.java:153) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:131) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:61) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:33) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:52) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:43) ~[spring-expression-5.3.23.jar:5.3.23]
    at org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory.createPreInvocationAttribute(ExpressionBasedAnnotationAttributeFactory.java:53) ~[spring-security-core-5.7.4.jar:5.7.4]
    ... 29 common frames omitted

Даже Intellij говорит, что что-то не так:

Обновление 3 (решено)

Это работает (спасибо за @dur):

      @PreAuthorize("@'com.example.demo.ExampleController'.hasPermission()")

Но Intellij вводит меня в заблуждение, это не сработает:

0 ответов

Другие вопросы по тегам