Восьмой выпуск введения компонента AccessDecisionVoter
В этом выпуске мы в основном представим компоненты контроля доступа, три мушкетера, отвечающие за роль правил авторизации -AccessDecisionVoterинтерфейс. И несколько баз, предоставляемых Spring Security по умолчанию.AccessDecisionVoterКласс реализации делает подробное описание, и, наконец, мы настроимAccessDecisionVoterРеализация используется для практической иллюстрации.
AccessDecisionVoterОписание интерфейса
Весенняя безопасностьAccessDecisionVoterOни
Пример настройки: по времени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Основное введение, мы узнали большой принцип дизайна:AccessDecisionVoterреализуется для удовлетворения соответствующих правилConfigAttribute. в целомAccessDecisionVoterС участиемConfigAttributeсоответствующий.
Вернемся к основным из них, которые мы представили в прошлом выпуске.ConfigAttributeвыполнить:
WebExpressionConfigAttribute на основе веб-выражений
SecurityConfig на основе аннотации @Secured
PostInvocationExpressionAttribute на основе аннотации @Pre-@Post
Мы можем легко найти соответствующую дверь его двери на картинке ниже.AccessDecisionVoter.Здесь мы сосредоточимся на конфигурации SecurityConfig, используемой в индивидуальном сценарии, и на двух ее значениях по умолчанию.AccessDecisionVoter:
RoleVoter
AuthenticatedVoter
Во-первых, давайте вспомним форму использования SecurityConfig, которая заключается в написании выражения с использованием аннотации @Secured:
мы изучилиAccessDecisionVoterа такжеConfigAttributeОб ассоциативных отношениях судят по методу опор, мы соответственноRoleVoterа такжеAuthenticatedVoterПросмотрите метод поддержки:
RoleVoterRoleVoterЭто основной компонент ролевых правил по умолчанию в 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;
}
}
}
AuthenticatedVoterAuthenticatedVoterСценарий использования весьма специфичен: это не контроль доступа на основе идентификационной информации, а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;
}
}
Наконец, мы завершаем основную бизнес-логику голосования: когда время нечетное, мы голосуем за него, а когда время четное, мы голосуем за чистое голосование.Без голосования.
Наконец, поговорим о том, как новыйAccessDecisionVoterдобавить к существующимAccessDecisionManagerсередина. Я также погуглил китайский мир и английский мир.Про этот удобный пример есть официальные документы, и там действительно всякое. Наиболее распространенным является реорганизация AccessDecisionManager и внедрение его обратно в Spring Security.Я не рекомендую создавать новый AccessDecisionManager в методе. Поскольку процесс инициализации AccessDecisionManager включает более чемAccessDecisionVoter, Случайно некоторые из поведений по умолчанию могут быть настроены неправильно из-за отсутствия набора компонентов.
Метод, который я рекомендую новичкам, состоит в том, чтобы создать новый класс Java Config для аннотаций на уровне методов, таких как расширение Secured, а затем переписать инициализацию в исходной среде.AccessDecisionManagerМетоды:
Хотя код может быть уродливым, и есть сильные типы конверсий, его относительно легко понять и многое контролировать.
После добавления конфигурации Java для MethodSecurityConfiguration мы увидим следующий журнал голосования, когда метод контроллера ограничен аннотацией @Secured("MINUTE_ODD"):
AccessDecisionVoterКомпоненты голосуют по очереди, и поскольку текущее время нечетное, наш MinuteBasedVoter отдает положительный голос со значением 1.
конец
Подробности этой проблемыAccessDecisionVoterЭтот компонент обеспечивает основное суждение и голосование для управления доступом. В то же время мы также узнали, как это работает, благодаря предоставлению по умолчанию и индивидуальной реализации фреймворка.
В следующем выпуске мы поставим последний основной компонентAccessDecisionManagerкак всеAccessDecisionVoterПодведите итоги голосования и объясните, как правила оценки влияют на окончательный результат авторизации.
Увидимся в следующий раз.