Восьмой выпуск введения компонента AccessDecisionVoter
В этом выпуске мы в основном представим компоненты контроля доступа, три мушкетера, отвечающие за роль правил авторизации -AccessDecisionVoter
интерфейс. И несколько баз, предоставляемых Spring Security по умолчанию.AccessDecisionVoter
Класс реализации делает подробное описание, и, наконец, мы настроимAccessDecisionVoter
Реализация используется для практической иллюстрации.
-
AccessDecisionVoter
Описание интерфейса - Весенняя безопасность
AccessDecisionVoter
Oни - Пример настройки: по времени
AccessDecisionVoter
1. Описание интерфейса AccessDecisionVoter
AccessDecisionVoter
Основная ответственность заключается в оценке соответствующих правил доступа и возможности авторизации текущих правил доступа.AccessDecisionVoter
Основной метод интерфейса фактически такой же, как и предыдущий.AuthenticationProvider
очень похожий.
boolean supports(ConfigAttribute attribute);
int vote(Authentication authentication, S object,
Collection<ConfigAttribute> attributes);
- Метод supports используется для определения того, является ли текущий
ConfigAttribute
Поддерживаются ли правила доступа; - Если он поддерживается, метод голосования оценит и проголосует за него и вернет соответствующий результат авторизации.
Есть три окончательных результата авторизации, а именно согласие, воздержание и возражение. Честно говоря, это правило по своему характеру похоже на голосование в Совете Безопасности ООН. Если для текущего посещения может быть несколько правил, каждое
AccessDecisionVoter
Отдайте свой собственный голос, окончательный результат голосования зависит от текущих правил голосования, например, больше 1/3 или больше половины. И решение правил голосования помещается вAccessDecisionManager
завершить.
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;
Во-вторых, весенняя безопасностьAccessDecisionVoter
Oни
через вышеуказанное дляAccessDecisionVoter
Основное введение, мы узнали большой принцип дизайна:AccessDecisionVoter
реализуется для удовлетворения соответствующих правилConfigAttribute
. в целомAccessDecisionVoter
С участиемConfigAttribute
соответствующий.
Вернемся к основным из них, которые мы представили в прошлом выпуске.ConfigAttribute
выполнить:
- WebExpressionConfigAttribute на основе веб-выражений
- SecurityConfig на основе аннотации @Secured
- PostInvocationExpressionAttribute на основе аннотации @Pre-@Post
Мы можем легко найти соответствующую дверь его двери на картинке ниже.
AccessDecisionVoter
.Здесь мы сосредоточимся на конфигурации SecurityConfig, используемой в индивидуальном сценарии, и на двух ее значениях по умолчанию.AccessDecisionVoter
: - RoleVoter
- AuthenticatedVoter Во-первых, давайте вспомним форму использования SecurityConfig, которая заключается в написании выражения с использованием аннотации @Secured:
@Secured("ROLE_USER")
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
мы изучилиAccessDecisionVoter
а такжеConfigAttribute
Об ассоциативных отношениях судят по методу опор, мы соответственноRoleVoter
а такжеAuthenticatedVoter
Просмотрите метод поддержки:
RoleVoter
RoleVoter
Это основной компонент ролевых правил по умолчанию в Spring Security. Чтобы создать пользователя в UserDetailsService, нам всем нужно установить информацию о роли для пользователя. В конфигурации по умолчанию информация о роли пользователя хранится в виде «ROLE_» + имя роли.
соответствующийRoleVoter
В методе supports будет оцениваться, начинается ли выражение с «ROLE_» в качестве соответствующего включенного правила. Если регулярное выражение начинается с ROLE_,RoleVoter
Он будет проходить, чтобы увидеть, есть ли соответствующая роль в аутентификации, если она существует, она вернет проход, а если она не существует, она вернет отказ.
public class RoleVoter implements AccessDecisionVoter<Object> {
// ~ Instance fields
// ================================================================================================
private String rolePrefix = "ROLE_";
// ~ Methods
// ========================================================================================================
public String getRolePrefix() {
return rolePrefix;
}
/**
* Allows the default role prefix of <code>ROLE_</code> to be overridden. May be set
* to an empty value, although this is usually not desirable.
*
* @param rolePrefix the new prefix
*/
public void setRolePrefix(String rolePrefix) {
this.rolePrefix = rolePrefix;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
}
else {
return false;
}
}
}
AuthenticatedVoter
AuthenticatedVoter
Сценарий использования весьма специфичен: это не контроль доступа на основе идентификационной информации, аAuhentication
Решение формы аутентификации. В предыдущей части аутентификации мы узнали, что в дизайне Spring Security мы можем использовать метод RememberMeService для авторизации входа без использования имени пользователя и пароля, а с помощью информации, хранящейся в файле cookie. В ежедневной инженерии для некоторых чувствительных операций мы требуем, чтобы текущий пользователь не был пользователем, который выполняет авторизацию и аутентификацию на основе истории.Логин расширяет действие сеанса, а не логин на основе куки месяц назад у пользователя. В этом сценарии мы можем использовать@Secured("IS_AUTHENTICATED_FULLY")
Чтобы ограничить пользователя полностью аутентифицированным пользователем, а не пользователем, аутентифицированным RememberMe.
существуетAuthenticatedVoter
В методе supports он будет судить, что текущее выражение является контролем доступа для трех поддерживаемых им методов аутентификации:
- IS_AUTHENTICATED_FULLY
- IS_AUTHENTICATED_REMEMBERED
- IS_AUTHENTICATED_ANONYMOUSLY
Если есть точное совпадение, текущий
Authentication
Оценивается режим авторизации объекта и возвращается соответствующий результат голосования.
public class AuthenticatedVoter implements AccessDecisionVoter<Object> {
// ~ Static fields/initializers
// =====================================================================================
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
// ~ Instance fields
// ================================================================================================
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
// ~ Methods
// ========================================================================================================
private boolean isFullyAuthenticated(Authentication authentication) {
return (!authenticationTrustResolver.isAnonymous(authentication) && !authenticationTrustResolver
.isRememberMe(authentication));
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute()) || IS_AUTHENTICATED_ANONYMOUSLY
.equals(attribute.getAttribute()))) {
return true;
}
else {
return false;
}
}
}
3. Индивидуальный пример: AccessDecisionVoter на основе времени
заAccessDecisionVoter
После базового понимания структуры, обязанностей и классов реализации, представленных в Spring Security. Мы подкрепляем это понимание индивидуальным примером.
Мы настроим управление доступом на основе времени, доступ к которому возможен только тогда, когда количество минут в системном времени нечетное, например, 10:01 можно получить доступ, но 10:02 нельзя.
правила дизайна
Во-первых, мы разрабатываем правила доступа. мы похожиRoleVoter
а такжеAuthenticatedVoter
Он также расширяется на основе выражений, аннотированных @Secured. Сформулированное нами правило называется "MINUTE_ODD". Когда уровень метода аннотирован @Secured("MINUTE_ODD"), это означает, что текущий метод может быть доступен только тогда, когда количество минут, удовлетворяющих системному времени, нечетно.
Настроить MinuteBasedVoter
Далее пишемMinuteBasedVoter
расширятьAuthenticatedVoter
.
public class MinuteBasedVoter implements AccessDecisionVoter {
}
Затем мы реализуем соответствующий метод поддержки, чтобы завершить наше суждение о наших предложенных правилах. Когда атрибут выражения входного параметра ConfigAttribute согласуется с нашей предустановкой «MINUTE_ODD», мы возвращаем значение true, чтобы сообщить платформе,MinuteBasedVoter
Для этого правила требуется операция голосования.
public class MinuteBasedVoter implements AccessDecisionVoter {
public static final String IS_MINUTE_ODD= "MINUTE_ODD";
@Override
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().equals(IS_MINUTE_ODD)) {
return true;
}
else {
return false;
}
}
@Override
public boolean supports(Class clazz) {
return true;
}
}
Наконец, мы завершаем основную бизнес-логику голосования: когда время нечетное, мы голосуем за него, а когда время четное, мы голосуем за чистое голосование.Без голосования.
@Override
public int vote(Authentication authentication, Object object, Collection collection) {
if(LocalDateTime.now().getMinute() % 2 != 0){
return ACCESS_GRANTED;
}else{
return ACCESS_DENIED;
}
}
Конфигурация Java
Наконец, поговорим о том, как новыйAccessDecisionVoter
добавить к существующимAccessDecisionManager
середина. Я также погуглил китайский мир и английский мир.Про этот удобный пример есть официальные документы, и там действительно всякое. Наиболее распространенным является реорганизация AccessDecisionManager и внедрение его обратно в Spring Security.Я не рекомендую создавать новый AccessDecisionManager в методе. Поскольку процесс инициализации AccessDecisionManager включает более чемAccessDecisionVoter
, Случайно некоторые из поведений по умолчанию могут быть настроены неправильно из-за отсутствия набора компонентов.
Метод, который я рекомендую новичкам, состоит в том, чтобы создать новый класс Java Config для аннотаций на уровне методов, таких как расширение Secured, а затем переписать инициализацию в исходной среде.AccessDecisionManager
Методы:
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@Configuration
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
AffirmativeBased affirmativeBased = (AffirmativeBased) super.accessDecisionManager();
affirmativeBased.getDecisionVoters().add(new MinuteBasedVoter());
return affirmativeBased;
}
}
Хотя код может быть уродливым, и есть сильные типы конверсий, его относительно легко понять и многое контролировать. После добавления конфигурации Java для MethodSecurityConfiguration мы увидим следующий журнал голосования, когда метод контроллера ограничен аннотацией @Secured("MINUTE_ODD"):
Secure object: ReflectiveMethodInvocation: public java.lang.String Attributes: [MINUTE_ODD]
Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@456f4439, returned: 0
Voter: org.springframework.security.access.vote.RoleVoter@38b13fa8, returned: 0
Voter: org.springframework.security.access.vote.AuthenticatedVoter@590fa701, returned: 0
Voter: com.newnil.demo.security.MinuteBasedVoter@135c04e9, returned: 1
Authorization successful
AccessDecisionVoter
Компоненты голосуют по очереди, и поскольку текущее время нечетное, наш MinuteBasedVoter отдает положительный голос со значением 1.
конец
Подробности этой проблемыAccessDecisionVoter
Этот компонент обеспечивает основное суждение и голосование для управления доступом. В то же время мы также узнали, как это работает, благодаря предоставлению по умолчанию и индивидуальной реализации фреймворка.
В следующем выпуске мы поставим последний основной компонентAccessDecisionManager
как всеAccessDecisionVoter
Подведите итоги голосования и объясните, как правила оценки влияют на окончательный результат авторизации.
Увидимся в следующий раз.