В документации четко сказано:
По умолчанию Spring Security требует, чтобы каждый запрос был аутентифицирован.
Я попробовал, и это не так.
Я создал простой Java-проект Spring Framework (без Spring Boot) и определил следующий bean-компонент:
@Bean
public SecurityFilterChain testFilterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.build();
}
Все запросы не требуют аутентификации. На самом деле нет даже цепочки фильтров со знаком AuthorizationFilter
.
Тот же результат, если не определять bean-компонент SecurityFilterChain
.
Я что-то упустил или документация просто неправильная?
Обновлено: проект настроен правильно. Класс конфигурации имеет аннотацию @EnableWebSecurity
, и как только я добавляю .authorizeHttpRequests().anyRequest().authenticated()
в конфигурацию, каждый запрос должен проходить аутентификацию.
трудно узнать, не видя результатов приложения. Я бы порекомендовал установить org.springframework.security
для отладки или отслеживания, и вы увидите, запускаются ли фильтры безопасности. Вполне возможно, что ваше приложение настраивает структуру. По опыту документация не ошибочна
Установка работает. Если я добавлю .authorizeHttpRequests().anyRequest().authenticated()
, то это сработает. Просто значение по умолчанию отличается от описанного.
Да, вам нужно прочитать следующие строки, и на самом деле вам нужно добавить как минимум:authorizeHttpRequests().anyRequest().authenticated()
Я прочитал эти строки, и это противоположно тому, что описано как поведение по умолчанию.
документация верна, вы просто вырвали ее из контекста. Полный отрывок:
По умолчанию Spring Security требует, чтобы каждый запрос был аутентифицирован. Тем не менее, каждый раз, когда вы используете экземпляр HttpSecurity, необходимо объявить свои правила авторизации.
каждый запрос аутентифицируется ДО тех пор, пока вы не предоставили свой собственный SecurityFilterChain
bean-компонент. Если да, то теперь он ведет себя так, как ВЫ его настроили.
Поскольку вы настаиваете на том, что у вас было другое поведение, я специально проверил это.
Я создал простое приложение весенней загрузки:
<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.asgarov</groupId>
<artifactId>spring-security-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-security-demo</name>
<description>spring-security-demo</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Затем я определил один класс контроллера
@RestController
public class HomeController {
@GetMapping
public String helloWorld() { return "Hello World"; }
}
и, как и ожидалось, при попытке доступа к localhost:8080
в браузере я был перенаправлен на страницу входа, вот журналы:
2024-07-17T20:41:00.287+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Securing GET /
2024-07-17T20:41:00.291+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2024-07-17T20:41:00.300+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] o.s.s.w.s.HttpSessionRequestCache : Saved request http://localhost:8080/?continue to session
2024-07-17T20:41:00.302+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@1e687528, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
2024-07-17T20:41:00.302+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@f0020b1
2024-07-17T20:41:00.303+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-2] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8080/login
2024-07-17T20:41:00.314+02:00 DEBUG 1873324 --- [spring-security-demo] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /login
После того, как я определил ту же конфигурацию, что и ваша:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain testFilterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.build();
}
}
Я мог бы получить доступ к выходным данным localhost:8080
также скручивания curl -v localhost:8080
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 11
< Date: Wed, 17 Jul 2024 18:45:26 GMT
<
* Connection #0 to host localhost left intact
Hello World
Итак, как сказано в документации, SpringBoot будет регистрировать defaultSecurityFilterChain ТОЛЬКО если вы его не определили. Код для него вы можете найти в классе SpringBootWebSecurityConfiguration
. Там вы увидите следующую конфигурацию:
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity
static class SecurityFilterChainConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
http.formLogin(withDefaults());
http.httpBasic(withDefaults());
return http.build();
}
}
Эта конфигурация просто гарантирует, что каждый запрос аутентифицирован, и регистрирует аутентификацию httpBasic по умолчанию и formLogin (как описано здесь).
А поскольку он помечен @ConditionalOnDefaultWebSecurity
, он будет активирован только тогда, когда пользователь не определил свою собственную конфигурацию
Хорошо, я создал совершенно новый проект с простым Spring MVC, и, похоже, он работает так, как задумано. Должно быть, я где-то допустил небольшую ошибку.
Теперь я знаю, что пошло не так. Я определил свою единственную цепочку безопасности и добавил к ней anyRequest().authenticated()
. Это сработало. Однако я также указал для него средство сопоставления безопасности. Когда вы делаете запрос, который не соответствует цепочке фильтров, он просто проходит. Значение Spring Security по умолчанию больше не применяется. Поэтому после определения цепочки фильтров вам всегда необходимо указать другую цепочку фильтров «соответствие всем запросам», которая требует аутентификации для всех запросов.
Вы добавили
@EnableWebSecurity
? Опубликуйте свою полную конфигурацию, а не просто фрагмент.