Я пытаюсь создать сервер 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();
}
Ожидание
Мои ожидания:
Поскольку я еще не установил никаких правил авторизации, приложение должно работать одинаково как с учетными данными, так и без них.
Действительный
Если я помещу учетные данные в заголовок, приложение будет работать как положено. Но если я ничего не добавлю в заголовок, запрос завершится с ошибкой 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]
Фильтр авторизации блокирует запрос, но я не понимаю, почему он блокируется, если нет какого-либо правила авторизации.
Поскольку я еще не установил никаких правил авторизации, приложение должно работать одинаково как с учетными данными, так и без них.
Да, вы установили правила авторизации.
.authorizeHttpRequests(request -> request
// All requests should be authenticated either with Basic or Anonymous Authentication
.anyRequest().authenticated())
Эта часть вашей конфигурации безопасности — это правила авторизации. authorizeHttpRequests
это выдает.
Вы указали правило, позволяющее разрешать только аутентифицированным пользователям, аноним не является аутентифицированным пользователем, следовательно, доступа нет.
.anyRequest().authenticated()
вы указали правило, согласно которому вы можете войти только как аутентифицированный пользователь. Anonymous не является аутентифицированным пользователем.