Изменить контекст безопасности для вызова метода с spring-security

В настоящее время я использую spring security и @PreAuthorize аннотации для защиты вызовов методов. Теперь я хочу изменить токен аутентификации для вызова метода, такого как run-as замена аутентификации весенняя безопасность позволяет мне это делать.

могу ли я настроить замену на базе каждого метода? В аннотации, выражение SpEL.... Если нет,можно ли выяснить в runAsManager, какой метод называется? Как настроить конфигурацию безопасности атрибуты для защищенного объекта, вообще?

2 ответов


я написал подробная статья при реализации Run-As в сочетании с @PreAuthorize.

1) реализовать собственный RunAsManager создает Authentication использовать во время выполнения метода на основе любой пользовательской логики. В приведенном ниже примере используется пользовательская аннотация, которая предоставляет дополнительную роль:

public class AnnotationDrivenRunAsManager extends RunAsManagerImpl {

        @Override
        public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
            if(!(object instanceof ReflectiveMethodInvocation) || ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class) == null) {
                return super.buildRunAs(authentication, object, attributes);
            }

            String roleName = ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class).value();

            if (roleName == null || roleName.isEmpty()) {
                return null;
            }

            GrantedAuthority runAsAuthority = new SimpleGrantedAuthority(roleName);
            List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
            // Add existing authorities
            newAuthorities.addAll(authentication.getAuthorities());
            // Add the new run-as authority
            newAuthorities.add(runAsAuthority);

            return new RunAsUserToken(getKey(), authentication.getPrincipal(), authentication.getCredentials(),
                    newAuthorities, authentication.getClass());
        }
    }

эта реализация будет искать пользовательский @RunAsRole аннотация защищенного метода (например,@RunAsRole("ROLE_AUDITOR")) и, если найдено, добавит данный авторитет (ROLE_AUDITOR в данном случае) в список своих полномочий. RunAsRole сам по себе является простой пользовательской аннотацией.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunAsRole {
    String value();
}

2) Создайте экземпляр менеджера:

<bean id="runAsManager"
    class="org.springframework.security.access.intercept.RunAsManagerImpl">
  <property name="key" value="my_run_as_key"/>
</bean>

3) прописать это:

<global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager">
    <expression-handler ref="expressionHandler"/>
</global-method-security>

4) Пример использования в контроллере:

@Controller
public class TransactionLogController {

   @PreAuthorize("hasRole('ROLE_REGISTERED_USER')") //Authority needed to access the method
   @RunAsRole("ROLE_AUDITOR") //Authority added by RunAsManager
   @RequestMapping(value = "/transactions",  method = RequestMethod.GET) //Spring MVC configuration. Not related to security
   @ResponseBody //Spring MVC configuration. Not related to security
   public List<Transaction> getTransactionLog(...) {
    ... //Invoke something in the backend requiring ROLE_AUDITOR
   {

   ... //User does not have ROLE_AUDITOR here
}

EDIT: Значение key на RunAsManagerImpl может быть все, что угодно. Вот отрывок из весной документы по его использованию:

To убедитесь, что вредоносный код не создает RunAsUserToken и представить это для гарантированного принятия RunAsImplAuthenticationProvider, хэш ключа хранится во всех сгенерированных токенах. Этот RunAsManagerImpl и RunAsImplAuthenticationProvider создается в контекст bean с тем же ключом:

<bean id="runAsManager"
    class="org.springframework.security.access.intercept.RunAsManagerImpl">

<bean id="runAsAuthenticationProvider"
    class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">

С помощью тот же ключ, каждый RunAsUserToken может быть подтверждено, что он был создан одобрено RunAsManagerImpl. The RunAsUserToken неизменяемо после создание для безопасности причины.


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

работает отлично.