Изменить контекст безопасности для вызова метода с 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
. TheRunAsUserToken
неизменяемо после создание для безопасности причины.
Я решил это, реализовав свой собственный RunAsManager
который проверяет наличие пользовательской аннотации для вызываемого метода и возвращает соответствующий токен.
работает отлично.