Статьи

Написание аннотации к языку выражения безопасности Spring

Язык выражений безопасности Spring очень полезен. Это помогает защитить ваши службы / веб-методы с помощью одной строки кода. Он поддерживает @PreAuthorize и @Secured. В следующих трех статьях я расскажу о том, как добавить пользовательское поведение в аннотацию @PreAuthorize. 

Часть 1. Настройка выражения hasPermission (). 
Часть 2. Добавление нового выражения безопасности метода настройки. 
Часть 3. Переопределение поведения по умолчанию пружинного выражения безопасности (например, hasRole (), allowAll () …).

В этой статье я расскажу, как добавить пользовательские правила для проверки разрешений в вашем приложении. Это несколько похоже на то, что описано в  посте Sold Craft  . Вы можете сослаться на это для более подробной информации.

Шаг 1: Добавьте конфигурацию в ваш весенний файл безопасности XML.

Сначала вы должны добавить DefaultMethodSecurityExpressionHandler. Он создаст экземпляр MethodSecurityExpressionRoot по умолчанию, который предоставляет вам все выражения безопасности по умолчанию (например, isAuthenticated () , isAnonymous () и т. Д.). 

Кроме того, вы должны добавить permissionEvaluator для этого ExpressionHandler. Если вы используете ACL Spring Spring , вы можете использовать AclPermissionEvaluator . В нашем случае мы бы создали BasePermissionEvaluator в качестве нашего оценщика разрешений. На шаге 2 вы увидите, что мы будем определять пользовательские правила в этом оценщике разрешений.

<sec: global-method-security pre-post-annotations = «enabled»>

  <sec:expression-handler ref="expressionHandler"/>
</sec:global-method-security>

<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandlerr">
    <property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>  

<bean id="permissionEvaluator" class="org.borislam.security.BasePermissionEvaluator"/>

Шаг 2. Создайте свой класс PermissionEvaluator

Вы должны определить класс, который реализует org.springframework.security.access.PermissionEvaluator . Вы должны переопределить метод hasPermission () и определить пользовательские правила в этом классе.

В моем примере объект user содержит HashMap, в котором хранятся разрешения пользователя. Я проверю разрешение String против этого Hashmap. Этот HashMap  заполняется при входе в систему фильтром. Эта часть не будет пропущена в этом примере. 

Для простоты я просто игнорирую параметр targetDomainObject в моем примере. Используя targetDomainObject , вы можете дополнительно определить правила безопасности для определенных объектов домена в вашем приложении.

открытый класс BasePermissionEvaluator реализует PermissionEvaluator {

 @Override
 public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
  boolean hasPermission = false;
  if ( authentication != null &&  permission instanceof String){

   //implement the permission checking of your application here   
   //you can just check if the input permission is within your permission list

   //In my example, the user object contains a HashMap which stored the permission of the user.
   //The HashMap<String, PrivilegeResult> is populated during using login by filter. This will not be shown in this example 

   User user = SecurityUtil.getUserCredential();
   HashMap<String, PrivilegeResult> pMap =user.getPrivilegeMap();
   PrivilegeResult privResult = pMap.get(permission); 
   hasPermission =  privResult.isAllowAccess();

  } else {
   hasPermission =false; 
  }
  return hasPermission;
 }

 @Override
 public boolean hasPermission(Authentication authentication,
   Serializable targetId, String targetType, Object permission) {
    throw new RimtimeException("Id and Class permissions are not supperted by this application");
 }
}

Шаг 3: Пример использования

Вы можете просто добавить свой  @PreAuthorize («hasPermission ()») для защиты вашего метода.

@PreAuthorize("hasPermission(#user, 'allowDoSomething')")
 public String doSomething()
 {
  //do something
  System.out.println("Do something");
 } 

Оригинальный пост