«1. Обзор

В этом руководстве мы покажем, как использовать аутентификацию Run-As в Spring Security с помощью простого сценария.

Объяснение Run-As на очень высоком уровне выглядит следующим образом: пользователь может выполнять некоторую часть логики от имени другого принципала с другими привилегиями.

2. RunAsManager

Первое, что нам нужно сделать, это настроить GlobalMethodSecurity и внедрить RunAsManager.

Это отвечает за предоставление временному объекту Authentication дополнительных привилегий:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected RunAsManager runAsManager() {
        RunAsManagerImpl runAsManager = new RunAsManagerImpl();
        runAsManager.setKey("MyRunAsKey");
        return runAsManager;
    }
}

Переопределяя runAsManager, мы заменяем реализацию по умолчанию в базовом классе, которая просто возвращает null.

Также обратите внимание на свойство ключа — фреймворк использует его для защиты/проверки временных объектов аутентификации (созданных с помощью этого менеджера).

Наконец, результирующий объект Authentication представляет собой RunAsUserToken.

3. Конфигурация безопасности

Чтобы аутентифицировать наш временный объект Authentication, мы настроим RunAsImplAuthenticationProvider:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    ...
    auth.authenticationProvider(runAsAuthenticationProvider());
}

@Bean
public AuthenticationProvider runAsAuthenticationProvider() {
    RunAsImplAuthenticationProvider authProvider = new RunAsImplAuthenticationProvider();
    authProvider.setKey("MyRunAsKey");
    return authProvider;
}

Мы, конечно, настроим его с тем же ключом, который мы использовали в менеджере — \», чтобы провайдер мог проверить, что объект аутентификации RunAsUserToken создан с использованием того же ключа.

4. Контроллер с @Secured

Теперь давайте посмотрим, как использовать замену аутентификации запуска от имени:

@Controller
@RequestMapping("/runas")
class RunAsController {

    @Secured({ "ROLE_USER", "RUN_AS_REPORTER" })
    @RequestMapping
    @ResponseBody
    public String tryRunAs() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return "Current User Authorities inside this RunAS method only " + 
          auth.getAuthorities().toString();
    }

}

Ключевым моментом здесь является новая роль – RUN_AS_REPORTER. Это триггер функции запуска от имени, поскольку фреймворк обрабатывает ее по-разному из-за префикса.

Когда запрос выполняется с помощью этой логики, у нас будет:

    Текущие права пользователя перед методом tryRunAs(): [ROLE_USER] Текущие права пользователя внутри метода tryRunAs(): [ROLE_USER, ROLE_RUN_AS_REPORTER] Временная аутентификация объект заменяет существующий объект Authentication только на время вызова метода tryRunAS()

5. Служба

Наконец, давайте реализуем реальную логику — простой уровень службы, который также защищен:

@Service
public class RunAsService {

    @Secured({ "ROLE_RUN_AS_REPORTER" })
    public Authentication getCurrentUser() {
        Authentication authentication = 
          SecurityContextHolder.getContext().getAuthentication();
        return authentication;
    }
}

~~ ~ Обратите внимание, что:

    Чтобы получить доступ к методу getCurrentUser(), нам нужно ROLE_RUN_AS_REPORTER Таким образом, мы можем вызывать метод getCurrentUser() только внутри нашего метода контроллера tryRunAs()

6. Внешний интерфейс

Далее мы используйте простой внешний интерфейс для тестирования нашей функции запуска от имени:

<html>
<body>
Current user authorities: 
    <span sec:authentication="principal.authorities">user</span>
<br/>
<span id="temp"></span>
<a href="#" onclick="tryRunAs()">Generate Report As Super User</a>
             
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
function tryRunAs(){
    $.get( "/runas" , function( data ) {
         $("#temp").html(data);
    });
}
</script>
</body>
</html>

Итак, теперь, когда пользователь инициирует действие «Создать отчет как суперпользователь», он получит временные полномочия ROLE_RUN_AS_REPORTER.

7. Заключение

В этом кратком руководстве мы рассмотрели простой пример использования функции замены аутентификации Spring Security Run-As.

Это руководство основано на кодовой базе, доступной на GitHub.