Доступ запрещен даже при использовании AnonymousAuthenticationFilter

Я пытаюсь создать сервер API, у которого есть конечные точки, доступные без аутентификации, и некоторые конечные точки, требующие аутентификации. Я хочу настроить Spring Security для аутентификации пользователя, когда это возможно, и при этом пропускать запрос, даже если он не может этого сделать, чтобы уровень контроллера/сервиса обрабатывал это.

Хотя у меня есть некоторый опыт работы в проектах Spring, но я новичок в настройке Spring Security, особенно Spring Security 6 с Spring boot 3.

У меня настроена Spring Security, как показано ниже:

// RestApiSecurityConfiguration.java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class RestApiSecurityConfiguration {

    @Bean
    public SecurityFilterChain signInSecurityFilterChain(HttpSecurity http,
                                                         DaoAuthenticationProvider daoAuthenticationProvider) throws Exception {

        // This filter chain should be applied to all routes
        http.securityMatcher("/**")

                .authorizeHttpRequests(request -> request
                        // All requests should be authenticated either with Basic or Anonymous Authentication
                        .anyRequest().authenticated())

                // Session is stateless
                .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))

                // Disable csrf and cors
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)

                // Enable BasicAuthenticationFilter with a custom DaoAuthenticationProvider
                .httpBasic(Customizer.withDefaults())
                .authenticationProvider(daoAuthenticationProvider)

                // Add AnonymousAuthenticationFilter
                .anonymous(Customizer.withDefaults());
        return http.build();
    }

Ожидание

Мои ожидания:

  1. Сначала попробуйте аутентифицировать звонящего с помощью BasicAuthenticationFilter
  2. Если BasicAuthenticationFilter не удается аутентифицироваться, все равно прикрепите какой-нибудь анонимный объект аутентификации с помощью AnonymousAuthenticationFilter и позвольте контроллеру/службе решить, что делать.

Поскольку я еще не установил никаких правил авторизации, приложение должно работать одинаково как с учетными данными, так и без них.

Действительный

Если я помещу учетные данные в заголовок, приложение будет работать как положено. Но если я ничего не добавлю в заголовок, запрос завершится с ошибкой 401 еще до того, как запрос достигнет контроллера.

2024-06-17T21:07:17.917-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Or [Mvc [pattern='/**']], Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@2129fad8, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1bfb6db7, org.springframework.security.web.context.SecurityContextHolderFilter@49863271, org.springframework.security.web.header.HeaderWriterFilter@3dc1e968, org.springframework.security.web.authentication.logout.LogoutFilter@7e4949ac, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1decdf51, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@71008711, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@2c76559e, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4f6c6a90, org.springframework.security.web.session.SessionManagementFilter@47143ab9, org.springframework.security.web.access.ExceptionTranslationFilter@3612b539, org.springframework.security.web.access.intercept.AuthorizationFilter@2f113e31]] (1/1)
2024-06-17T21:07:17.918-07:00 DEBUG 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /api/posts
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (5/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.s.w.a.logout.LogoutFilter            : Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking BasicAuthenticationFilter (6/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter  : Did not process authentication request since failed to find username and password in Basic Authorization header
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (7/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (8/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (9/12)
2024-06-17T21:07:17.918-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking SessionManagementFilter (10/12)
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] estMatcherDelegatingAuthorizationManager : Authorizing GET /api/posts
2024-06-17T21:07:17.919-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] estMatcherDelegatingAuthorizationManager : Checking authorization on GET /api/posts using org.springframework.security.authorization.AuthenticatedAuthorizationManager@21795633
2024-06-17T21:07:17.922-07:00 TRACE 19168 --- [spring-template] [nio-4000-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied

org.springframework.security.access.AccessDeniedException: Access Denied
    at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:98) ~[spring-security-web-6.3.0.jar:6.3.0]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.3.0.jar:6.3.0]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.3.0.jar:6.3.0]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.3.0.jar:6.3.0]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) ~[spring-security-web-6.3.0.jar:6.3.0]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) ~[spring-security-web-6.3.0.jar:6.3.0]

Фильтр авторизации блокирует запрос, но я не понимаю, почему он блокируется, если нет какого-либо правила авторизации.

.anyRequest().authenticated() вы указали правило, согласно которому вы можете войти только как аутентифицированный пользователь. Anonymous не является аутентифицированным пользователем.
M. Deinum 18.06.2024 08:05
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Поскольку я еще не установил никаких правил авторизации, приложение должно работать одинаково как с учетными данными, так и без них.

Да, вы установили правила авторизации.

.authorizeHttpRequests(request -> request
                        // All requests should be authenticated either with Basic or Anonymous Authentication
                        .anyRequest().authenticated())

Эта часть вашей конфигурации безопасности — это правила авторизации. authorizeHttpRequests это выдает.

Вы указали правило, позволяющее разрешать только аутентифицированным пользователям, аноним не является аутентифицированным пользователем, следовательно, доступа нет.

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