Добавление дополнительных методов в настраиваемый оценщик разрешений? - PullRequest
1 голос
/ 14 июля 2020

У меня есть оценщик таможенных разрешений, настроенный примерно так:

public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object target, Object permission) {
        //do stuff
    }

Затем в моей конфигурации у меня есть

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private MyPermissionEvaluator myPermissionEvaluator;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
        methodSecurityExpressionHandler.setPermissionEvaluator(myPermissionEvaluator);
        return methodSecurityExpressionHandler;
    }

Это отлично работает для стандартных случаев использования при использовании " hasPermission "в preAuth для безопасности моих методов, например

@PreAuthorize("hasPermission(#model.appName, 'RETRIVE')")

Однако теперь мне нужно добавить собственный метод, чтобы проверить что-то еще, а hasPermission мне недостаточно, мне нужно иметь свой собственный метод, поэтому Я попытался добавить его в текущий оценщик разрешений

public boolean myNewMethod(String app) {
        // do something
    }

Затем в моей сигнатуре метода я обновил preAuth, чтобы получить

@PreAuthorize("hasPermission(#model.appName, 'RETRIVE') or myNewMethod(#model.value)")

, это дает следующую ошибку: " org.springframework.expression.spel.SpelEvaluationException: EL1004E: Вызов метода: Метод hasRoleAndStoreFor (java .lang.String) не может быть найден для типа org.springframework.security.access.expression.method.MethodSecurityExpression Root " *

Затем я попытался обновить preAuth до

@PreAuthorize("hasPermission(#model.appName, 'RETRIVE') or @myPermissionEvaluator.myNewMethod(#model.value)")

, и это дает мне следующую ошибку:

* 102 7 * В контексте не зарегистрирован преобразователь bean-компонентов для разрешения доступа к bean-компоненту myPermissionEvaluator

Затем я попытался переместить метод в новую службу и выполнить

@PreAuthorize("hasPermission(#model.appName, 'RETRIVE') or @newService.myNewMethod(#model.value)")

но не повезло.

Есть идеи? Я не понимаю, как это сделать

Ответы [ 2 ]

0 голосов
/ 14 июля 2020

Вот еще один способ, который сработал для меня.

  1. Реализуйте примечание root, где начинается оценка всех выражений безопасности. Добавьте свой собственный метод в этот класс.

     public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
    
     private Authentication auth;
    
     public CustomMethodSecurityExpressionRoot( Authentication authentication) {
       super(authentication);
       this.auth=authentication;
    
     }
    
     // Your custom method
     public boolean myNewMethod(String app) {
      // do something
     }
    
     @Override
     public void setFilterObject(Object filterObject) {
       // TODO Auto-generated method stub
     }
    
     @Override
     public Object getFilterObject() {
      // TODO Auto-generated method stub
      return null;
     }
    
     @Override
     public void setReturnObject(Object returnObject) {
      // TODO Auto-generated method stub
     }
    
     @Override
     public Object getReturnObject() {
      // TODO Auto-generated method stub
      return null;
     }
    
     @Override
     public Object getThis() {
      // TODO Auto-generated method stub
      return null;
     }
    
    }
    
  2. Вставьте CustomMethodSecurityExpression Root в CustomMethodSecurityExpressionHandler класс, который расширяет DefaultMethodSecurityExpressionHandler .

     public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
    
     private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
    
     private ApplicationContext applicationContext;
    
    
     @Override
     public MethodSecurityExpressionOperations createSecurityExpressionRoot( Authentication authentication,
             MethodInvocation invocation) {
         CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
         root.setPermissionEvaluator(getPermissionEvaluator());
         root.setTrustResolver(this.trustResolver);
         root.setRoleHierarchy(getRoleHierarchy());
         return root;
     }
    
      @Override
      public void setApplicationContext(ApplicationContext applicationContext){
             super.setApplicationContext(applicationContext);
             this.applicationContext = applicationContext;
    
      }
    }
    
  3. Следующее использование CustomMethodSecurityExpressionHandler в конфигурации безопасности метода.

     @Configuration
     @EnableGlobalMethodSecurity(prePostEnabled = true)
     public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    
     @Autowired
     ApplicationContext applicationContext;
    
     @Override
     protected MethodSecurityExpressionHandler createExpressionHandler() {
         CustomMethodSecurityExpressionHandler expressionHandler = 
           new CustomMethodSecurityExpressionHandler();
         expressionHandler.setApplicationContext(applicationContext);
         return expressionHandler;
     }
    
    }
    
  4. Сейчас вы все настроены на использование вашего собственного метода в контроллере.

    @PreAuthorize("myNewMethod(#model.value)")
    

Кроме того, если вам нужна какая-либо услуга для автоматического подключения в классе CustomMethodSecurityExpression Root, вы для этого нужно использовать сеттер.

private UserService userService;


private PostService postService;

public void setUserService(UserService userService){
  this.userService = userService;
}
public void setPostService(PostService postService) {
  this.postService = postService;
}

И вам нужно вызвать эти сеттеры в CustomMethodSecurityExpressionHandler class.

root.setUserService(applicationContext.getBean(UserService.class));
root.setPostService(applicationContext.getBean(PostService.class));
0 голосов
/ 14 июля 2020

Если вы можете сделать метод stati c, используйте

T(com.foo.MyClass).myNewMethod(#model.value)

...