Каково поведение Spring Security по умолчанию для запросов?

В документации четко сказано:

По умолчанию 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() в конфигурацию, каждый запрос должен проходить аутентификацию.

Вы добавили @EnableWebSecurity? Опубликуйте свою полную конфигурацию, а не просто фрагмент.

M. Deinum 17.07.2024 13:58

трудно узнать, не видя результатов приложения. Я бы порекомендовал установить org.springframework.security для отладки или отслеживания, и вы увидите, запускаются ли фильтры безопасности. Вполне возможно, что ваше приложение настраивает структуру. По опыту документация не ошибочна

Darren Forsythe 17.07.2024 13:58

Установка работает. Если я добавлю .authorizeHttpRequests().anyRequest().authenticated(), то это сработает. Просто значение по умолчанию отличается от описанного.

T3rm1 17.07.2024 14:14

Да, вам нужно прочитать следующие строки, и на самом деле вам нужно добавить как минимум:authorizeHttpRequests().anyRequest().authenticated()

Mr_Thorynque 17.07.2024 14:21

Я прочитал эти строки, и это противоположно тому, что описано как поведение по умолчанию.

T3rm1 17.07.2024 14:24
1
5
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

документация верна, вы просто вырвали ее из контекста. Полный отрывок:

По умолчанию 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, и, похоже, он работает так, как задумано. Должно быть, я где-то допустил небольшую ошибку.

T3rm1 18.07.2024 17:14

Теперь я знаю, что пошло не так. Я определил свою единственную цепочку безопасности и добавил к ней anyRequest().authenticated(). Это сработало. Однако я также указал для него средство сопоставления безопасности. Когда вы делаете запрос, который не соответствует цепочке фильтров, он просто проходит. Значение Spring Security по умолчанию больше не применяется. Поэтому после определения цепочки фильтров вам всегда необходимо указать другую цепочку фильтров «соответствие всем запросам», которая требует аутентификации для всех запросов.

T3rm1 19.07.2024 15:10

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

Выход из системы, инициированный RP, на сервере авторизации Spring не работает
Конечная точка Spring Boot @PostMapping не поражена, пока @GetMapping работает после добавления securityFilterChain
Как сохранить области, пользователей и роли в Keycloak при использовании Docker и Docker Compose для его запуска
AccessDeniedHandler не вызывается при использовании AadResourceServerHttpSecurityConfigurer
Требование токена CSRF, если реализован JWT
Не могу понять, почему мой логинконтроллер не может аутентифицировать пользователя. Spring Security сводит меня с ума
API не может получить доступ к частным конечным точкам (403 запрещено), даже если пользователь прошел аутентификацию
Bean-компонент типа «org.springframework.security.crypto.password.PasswordEncoder», который не удалось найти
Проблема Spring Security с JWT: невозможно создать подкласс финального класса JwtAuthenticationProvider
Проблемы с пользовательским поставщиком аутентификации при весенней загрузке 3.3.0