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.class
не имеет зарегистрированного порядка и не может использоваться с addFilterAfter или addFilterBefore, почему Spring Security не выдает ошибку времени компиляции, чтобы предотвратить это?
Каким образом вызов метода должен приводить к ошибке времени компиляции? Это будет работать только в том случае, если подпись не будет совпадать.
Это может показаться необычной мыслью, но что, если метод: public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter)
изменить на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends FilterChain> beforeFilter)
Вызовет ли эта модификация какие-либо проблемы?
Это изменение не имело бы смысла. Вы хотите добавить фильтр до или после другого фильтра. Добавление изменения этого параметра на FilterChain
вообще не поможет (и не имеет никакого смысла).
В сообщении об ошибке говорится:
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 не выдает ошибку времени компиляции, чтобы предотвратить это?
Ошибки времени компиляции могут возникать только компилятором Java (именно поэтому они называются временем компиляции) при обнаружении синтаксической ошибки Java.
Это может показаться необычной мыслью, но что, если метод: public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter)
изменить на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends ChainFilter> beforeFilter)
Вызовет ли эта модификация какие-либо проблемы?
Класса ChainFilter
нет, поэтому это даже не скомпилируется.
извините, нет ChainFilter
-> FilterChain.class
были изменены на: public HttpSecurity addFilterBefore(Filter filter, Class<? extends FilterChain> beforeFilter)
Вызовет ли это изменение какие-либо проблемы?
Потому что Filter и FilterChain — это две разные вещи. Как следует из названия, фильтр — это один фильтр, FilterChain — это цепочка фильтров, если можно, список.
но вам следует задать себе вопрос: зачем вам вообще добавлять собственный фильтр? Совершенно очевидно, что вы полный новичок, так почему же вы не читаете документацию и не используете встроенные фильтры, которые уже включены в Spring Security? Почему встроенные функции не соответствуют вашим потребностям?
Порядок размещения фильтра наследуется от класса FilterOrderRegistration. Для addFilterBefore
и addFilterAfter
необходимо знать порядок фильтра, чтобы знать, где разместить добавляемый фильтр (до/после него).
AuthenticationFilter
нет в этом списке заказов, поэтому использование addFilterBefore
/addFilterAfter
не удастся, поскольку он не может определить, где разместить фильтр.
addFilterBefore
/addFilterAfter
в конечном итоге делегирует все методу private
addFilterAtOffsetOf
. Это вызывает исключение, если заказ не найден.
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 не выдает ошибку времени компиляции, чтобы предотвратить это?
Эту ошибку вы получаете, потому что пытаетесь добавить свой собственный фильтр аутентификации до или после AuthenticationFilter
, но в библиотеке Spring-Security такого класса фильтра не существует.
и это сработало после добавления UsernamePasswordAuthenticationFilter
, потому что этот фильтр существует в библиотеке безопасности Spring.
вы можете проверить список всех фильтров. Перейдите в библиотеку org.springframework.security.web
--> папка аутентификации.
Ошибка о том, почему кажется довольно ясной.
AuthenticationFilter does not have a registered order
, вы можете использовать только фильтры, которые имеют определенный порядок вaddFilterAfter
/addFilterBefore
, как будто у них нет порядка (т. е. они являются частью обычной цепочки), как конфигурация будет определять, где разместить фильтр?