Как создать пользовательские методы для использования в выражениях выражения выражения весны безопасности

Я хотел бы создать class, который добавляет пользовательские методы для использования в языке выражения весны безопасности для авторизации на основе метода через annotations.

Например, я хотел бы создать собственный метод, например customMethodReturningBoolean, который будет использоваться так:

@PreAuthorize("customMethodReturningBoolean()") public void myMethodToSecure() { // whatever } 

Мой вопрос таков. Если это возможно, какой class должен быть подclassом для создания моих настраиваемых методов, как бы я решил настроить его в конфигурационных файлах весны xml и пришел ли кто-нибудь, чтобы я привел пример пользовательского метода, используемого таким образом?

Вам нужно подclassифицировать два classа.

Сначала установите новый обработчик выражения метода

    

myMethodSecurityExpressionHandler будет подclassом DefaultMethodSecurityExpressionHandler который переопределяет createEvaluationContext() , устанавливая подclass MethodSecurityExpressionRoot в MethodSecurityEvaluationContext .

Например:

 @Override public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) { MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer); MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth); root.setTrustResolver(trustResolver); root.setPermissionEvaluator(permissionEvaluator); root.setRoleHierarchy(roleHierarchy); ctx.setRootObject(root); return ctx; } 

Ни один из вышеупомянутых методов не будет работать больше. Похоже, что Spring прошла долгий путь, чтобы пользователи не переопределили SecurityExpressionRoot.

EDIT 11/19/14 Настройка Spring для использования аннотаций безопасности:

  ...  

Создайте bean-компонент следующим образом:

 @Component("mySecurityService") public class MySecurityService { public boolean hasPermission(String key) { return true; } } 

Затем сделайте что-то подобное в jsp:

    

Или аннотируйте метод:

 @PreAuthorize("@mySecurityService.hasPermission('special')") public void doSpecialStuff() { ... } 

И помните: если вы используете Spring, и вам приходится решать проблему, расширяя classы, переопределяя методы, реализуя интерфейсы и т. Д. … тогда вы, вероятно, что-то делаете неправильно. Это все annotations и xml, поэтому мы очень любим Spring, а не (старые версии) EJB.

Кроме того, вы можете использовать Spring Expression Language в своих @PreAuthorize для доступа к текущей аутентификации, а также аргументам метода.

Например:

 @Component("mySecurityService") public class MySecurityService { public boolean hasPermission(Authentication authentication, String foo) { ... } } 

Затем обновите свой @PreAuthorize чтобы он соответствовал новой сигнатуре метода:

 @PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)") public void doSpecialStuff(String foo) { ... } 

Спасибо ericacm , но это не работает по нескольким причинам:

  • Свойства DefaultMethodSecurityExpressionHandler являются частными (нежелательные видимости)
  • По крайней мере, в моем Eclipse я не могу разрешить объект MethodSecurityEvaluationContext

Различия в том, что мы вызываем существующий метод createEvaluationContext, а затем добавляем наш пользовательский корневой объект. Наконец, я просто вернул тип объекта StandardEvaluationContext, поскольку метод MethodSecurityEvaluationContext не будет разрешен в компиляторе (они оба из одного и того же интерфейса). Это код, который я сейчас имею в производстве.

Сделать методSecurityExpressionHandler использовать наш собственный корень:

 public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { // parent constructor public CustomMethodSecurityExpressionHandler() { super(); } /** * Custom override to use {@link CustomSecurityExpressionRoot} * * Uses a {@link MethodSecurityEvaluationContext} as the EvaluationContext implementation and * configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object. */ @Override public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) { // due to private methods, call original method, then override it's root with ours StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi); ctx.setRootObject( new CustomSecurityExpressionRoot(auth) ); return ctx; } } 

Это заменяет корень по умолчанию, расширяя SecurityExpressionRoot . Здесь я переименовал hasRole в hasEntitlement:

 public class CustomSecurityExpressionRoot extends SecurityExpressionRoot { // parent constructor public CustomSecurityExpressionRoot(Authentication a) { super(a); } /** * Pass through to hasRole preserving Entitlement method naming convention * @param expression * @return boolean */ public boolean hasEntitlement(String expression) { return hasRole(expression); } } 

Наконец обновите securityContext.xml (и убедитесь, что он ссылается на ваш applcationContext.xml):

       

Примечание: аннотация @Secured не принимает это переопределение при прохождении через другой обработчик проверки. Итак, в приведенном выше xml я отключил их, чтобы предотвратить путаницу.

  • Объявление Spring Bean в контексте родительского контекста и дочернего контекста
  • Могу ли я сделать настраиваемый controller зеркальным отображением classов Spring-Data-Rest / Spring-Hateoas?
  • Включить сериализацию HAL в Spring Boot для пользовательского метода controllerа
  • Spring MVC @PathVariable с точкой (.) Получает усеченный
  • Как получить пользовательскую информацию пользователя от сервера авторизации сервера / пользователя OAuth2
  • Весенняя загрузка - обращение к спящему SessionFactory
  • Как проверить поддержку декларативного кэширования Spring в хранилищах Spring Data?
  • Как создать динамический «в (...)» sql-список через Spring JdbcTemplate?
  • Нет типов Spring WebApplicationInitializer, обнаруженных на пути к classам
  • applicationContext не находит controllerы для контекста сервлета
  • Как сделать условную автоматическую проводку весной?
  • Давайте будем гением компьютера.