У меня вопрос о «AuthenticationFilter.class» в Spring Security

http
        .csrf(AbstractHttpConfigurer::disable)
        .cors(AbstractHttpConfigurer::disable)
        .addFilterAfter(CoustomAuthCheckFilter, UsernamePasswordAuthenticationFilter.class)
...

Я использовал AuthenticationFilter.class в методе addFilterAfter и столкнулся с ошибкой. После изменения на UsernamePasswordAuthenticationFilter.class все заработало. Почему компилятор не выдает ошибку при использовании AuthenticationFilter.class, даже если это не конкретный фильтр, который обычно используется напрямую?»

пытаться

http
        .csrf(AbstractHttpConfigurer::disable)
        .cors(AbstractHttpConfigurer::disable)
        .addFilterAfter(CoustomAuthCheckFilter, AuthenticationFilter.class)

Я ожидал старта сервера. но

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'filterChain' defined in class path resource [com/wincubemkt/mediagw/global/config/SecurityConfig.class]: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'filterChain' threw exception with message: The Filter class org.springframework.security.web.authentication.AuthenticationFilter does not have a registered order
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:895) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:848) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1439) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.11.jar:6.1.11]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.2.jar:3.3.2]
    at com.wincubemkt.mediagw.MEDIAGWApplication.main(MEDIAGWApplication.java:11) ~[main/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.2.jar:3.3.2]

Я столкнулся со следующей ошибкой при использовании AuthenticationFilter.class

Ошибка о том, почему кажется довольно ясной. AuthenticationFilter does not have a registered order, вы можете использовать только фильтры, которые имеют определенный порядок в addFilterAfter/addFilterBefore, как будто у них нет порядка (т. е. они являются частью обычной цепочки), как конфигурация будет определять, где разместить фильтр?

M. Deinum 07.08.2024 09:35

Спасибо вам за разъяснение. Учитывая, что AuthenticationFilter.class не имеет зарегистрированного порядка и не может использоваться с addFilterAfter или addFilterBefore, почему Spring Security не выдает ошибку времени компиляции, чтобы предотвратить это?

minjun 07.08.2024 09:43

Каким образом вызов метода должен приводить к ошибке времени компиляции? Это будет работать только в том случае, если подпись не будет совпадать.

M. Deinum 07.08.2024 10:19

Это может показаться необычной мыслью, но что, если метод: public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) изменить на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends FilterChain> beforeFilter) Вызовет ли эта модификация какие-либо проблемы?

minjun 07.08.2024 10:30

Это изменение не имело бы смысла. Вы хотите добавить фильтр до или после другого фильтра. Добавление изменения этого параметра на FilterChain вообще не поможет (и не имеет никакого смысла).

M. Deinum 07.08.2024 10:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
64
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

В сообщении об ошибке говорится:

org.springframework.security.web.authentication.AuthenticationFilter does not have a registered order

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

  • addFilterBefore()
  • addFilterAfter()

второй параметр должен иметь Order, установленный Spring внутри FilterOrderRegistration. Вот фрагмент из FilterOrderRegistration:

//...
put(X509AuthenticationFilter.class, order.next());
put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
this.filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", order.next());
this.filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter", order.next());
this.filterToOrder.put("org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter", order.next());
put(UsernamePasswordAuthenticationFilter.class, order.next());
order.next(); // gh-8105
//...

как вы можете видеть среди других классов, он устанавливает порядок для UsernamePasswordAuthenticationFilter. Однако если вы посмотрите на полный код, он не регистрирует заказ на AuthenticationFilter (по какой-то причине).


Когда вы вызываете addFilterBefore или addFilterAfter, они оба внутренне ссылаются на метод addFilterAtOffsetOf, который затем выдает исключение, с которым вы столкнулись:

@Override
public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
    return addFilterAtOffsetOf(filter, 1, afterFilter);
}

@Override
public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) {
    return addFilterAtOffsetOf(filter, -1, beforeFilter);
}

private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
    Integer registeredFilterOrder = this.filterOrders.getOrder(registeredFilter);
    if (registeredFilterOrder == null) {
        throw new IllegalArgumentException(
                "The Filter class " + registeredFilter.getName() + " does not have a registered order");
    }
    int order = registeredFilterOrder + offset;
    this.filters.add(new OrderedFilter(filter, order));
    this.filterOrders.put(filter.getClass(), order);
    return this;
}

Вот почему на момент написания этой статьи (Spring Security 6.3.1) вы ограничены следующими фильтрами, на которые вы можете ссылаться в addFilterAfter, поскольку это единственные, которые зарегистрированы в FilterOrderRegistration:

 - DisableEncodeUrlFilter.class
 - ForceEagerSessionCreationFilter.class
 - ChannelProcessingFilter.class
 - WebAsyncManagerIntegrationFilter.class
 - SecurityContextHolderFilter.class
 - SecurityContextPersistenceFilter.class
 - HeaderWriterFilter.class
 - CorsFilter.class
 - CsrfFilter.class
 - LogoutFilter.class
 - X509AuthenticationFilter.class
 - AbstractPreAuthenticatedProcessingFilter.class
 - UsernamePasswordAuthenticationFilter.class
 - DefaultLoginPageGeneratingFilter.class
 - DefaultLogoutPageGeneratingFilter.class
 - ConcurrentSessionFilter.class
 - DigestAuthenticationFilter.class
 - BasicAuthenticationFilter.class
 - RequestCacheAwareFilter.class
 - SecurityContextHolderAwareRequestFilter.class
 - JaasApiIntegrationFilter.class
 - RememberMeAuthenticationFilter.class
 - AnonymousAuthenticationFilter.class
 - SessionManagementFilter.class
 - ExceptionTranslationFilter.class
 - FilterSecurityInterceptor.class
 - AuthorizationFilter.class
 - SwitchUserFilter.class

Спасибо вам за разъяснение. Учитывая, что AuthenticationFilter.class не имеет зарегистрированного порядка и не может использоваться с addFilterAfter или addFilterBefore, почему Spring Security не выдает ошибку времени компиляции, чтобы предотвратить это?

minjun 07.08.2024 09:52

Ошибки времени компиляции могут возникать только компилятором Java (именно поэтому они называются временем компиляции) при обнаружении синтаксической ошибки Java.

J Asgarov 07.08.2024 09:57

Это может показаться необычной мыслью, но что, если метод: public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) изменить на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends ChainFilter> beforeFilter) Вызовет ли эта модификация какие-либо проблемы?

minjun 07.08.2024 10:12

Класса ChainFilter нет, поэтому это даже не скомпилируется.

M. Deinum 07.08.2024 10:20

извините, нет ChainFilter -> FilterChain.class были изменены на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends FilterChain> beforeFilter) Вызовет ли это изменение какие-либо проблемы?

minjun 07.08.2024 10:32

Потому что Filter и FilterChain — это две разные вещи. Как следует из названия, фильтр — это один фильтр, FilterChain — это цепочка фильтров, если можно, список.

Toerktumlare 07.08.2024 19:18

но вам следует задать себе вопрос: зачем вам вообще добавлять собственный фильтр? Совершенно очевидно, что вы полный новичок, так почему же вы не читаете документацию и не используете встроенные фильтры, которые уже включены в Spring Security? Почему встроенные функции не соответствуют вашим потребностям?

Toerktumlare 07.08.2024 19:19

Порядок размещения фильтра наследуется от класса FilterOrderRegistration. Для addFilterBefore и addFilterAfter необходимо знать порядок фильтра, чтобы знать, где разместить добавляемый фильтр (до/после него).

AuthenticationFilter нет в этом списке заказов, поэтому использование addFilterBefore/addFilterAfter не удастся, поскольку он не может определить, где разместить фильтр.

addFilterBefore/addFilterAfter в конечном итоге делегирует все методу privateaddFilterAtOffsetOf. Это вызывает исключение, если заказ не найден.

private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
    Integer registeredFilterOrder = this.filterOrders.getOrder(registeredFilter);
    if (registeredFilterOrder == null) {
        throw new IllegalArgumentException(
                "The Filter class " + registeredFilter.getName() + " does not have a registered order");
    }
    int order = registeredFilterOrder + offset;
    this.filters.add(new OrderedFilter(filter, order));
    this.filterOrders.put(filter.getClass(), order);
    return this;
}

Спасибо вам за разъяснение. Учитывая, что AuthenticationFilter.class не имеет зарегистрированного порядка и не может использоваться с addFilterAfter или addFilterBefore, почему Spring Security не выдает ошибку времени компиляции, чтобы предотвратить это?

minjun 07.08.2024 09:53

Эту ошибку вы получаете, потому что пытаетесь добавить свой собственный фильтр аутентификации до или после AuthenticationFilter, но в библиотеке Spring-Security такого класса фильтра не существует.

и это сработало после добавления UsernamePasswordAuthenticationFilter, потому что этот фильтр существует в библиотеке безопасности Spring.

вы можете проверить список всех фильтров. Перейдите в библиотеку org.springframework.security.web --> папка аутентификации.

Другие вопросы по теме