Java Spring Boot 3 Spring Security OAuth2 Неаутентифицированная конечная точка

Я хочу, чтобы определенная конечная точка /public/info была доступна без аутентификации.

Мое приложение.yaml

spring:
  application:
    name: team1
  security:
    oauth2:
      client:
        provider:
          # provider name used for registration
          demo:
            # Keycloak realm URL: "{keycloak-url}/realms/{realm-name}"
            issuer-uri: 
        registration:
          # client-id from Keycloak client configuration
          demo-client:
            # provider from above
            provider: demo
            # client-id from Keycloak client configuration
            client-id:
            client-secret:
            scope: openid
            authorization-grant-type: authorization_code
            redirect-uri:

server:
  port: 8080

Моя конфигурация безопасности:

@Configuration
@EnableWebSecurity
class SecurityConfiguration{

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> {
                authorize.requestMatchers("/public/info").permitAll();
                authorize.anyRequest().authenticated();}
            ).oauth2Login(Customizer.withDefaults());
        return http.build();
    }
   
}

Разве /public/info не должен быть доступен без аутентификации? Меня всегда перенаправляют на keycloak.

Конечная точка /public/info:

@GetMapping(path = "/public/info")
public String hello() {
    return "Hello";
}

Мой build.gradle - возможно, здесь может быть проблема с использованием неправильной версии.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.0'
    id 'io.spring.dependency-management' version '1.1.5'
}

group = 'at.ac.fhwn'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

То, что вы показываете, верно. Должно быть, вы скрываете что-то, что ломает ваше приложение.

Хороший вопрос должен содержать:

  • зависимости (все, с версиями)
  • конфигурация (все со свойствами, заметным исключением являются значения секретов)
  • DEBUG или TRACE журналы, показывающие проблему

Полное приложение (которое работает):

<?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.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Configuration
  @EnableWebSecurity
  static class SecurityConfiguration {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
      http.authorizeHttpRequests(authorize -> {
        authorize.requestMatchers("/public/info").permitAll();
        authorize.anyRequest().authenticated();
      }).oauth2Login(Customizer.withDefaults());
      return http.build();
    }

  }

  @RestController
  static class PublicController {
    @GetMapping(path = "/public/info")
    public String hello() {
      return "Hello";
    }
  }

  @RestController
  static class PrivateController {
    @GetMapping(path = "/private/info")
    public String hello(Authentication auth) {
      return "Hello %s".formatted(auth.getName());
    }
  }

}
spring:
  application:
    name: demo
  security:
    oauth2:
      client:
        provider:
          demo:
            issuer-uri: https://oidc.c4-soft.com/auth/realms/quiz
        registration:
          demo-client:
            provider: demo
            client-id: change-me
            client-secret: change-me
            scope: openid
            authorization-grant-type: authorization_code

server:
  port: 8080

logging:
  level:
    root: INFO
    org:
      springframework:
        security: DEBUG
        boot: INFO

И прохождение интеграционных тестов показало, что все работает как положено:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@AutoConfigureMockMvc
class DemoApplicationTests {
  @Autowired
  MockMvc api;

  @Test
  @WithAnonymousUser
  void givenRequestIsAnonymous_whenGetPublicInfo_thenOk() throws Exception {
    api.perform(get("/public/info")).andExpect(status().isOk());
  }

  @Test
  @WithAnonymousUser
  void givenRequestIsAnonymous_whenGetPrivateInfo_thenRedirectToLogin() throws Exception {
    api.perform(get("/private/info")).andExpect(status().is3xxRedirection());
  }

  @Test
  void givenUserIsAuthenticated_whenGetPrivateInfo_thenOk() throws Exception {
    api.perform(get("/private/info").with(oauth2Login())).andExpect(status().isOk());
  }

}

Спасибо за ответ, это было почти полное моё приложение, в application.yaml больше не было конфигов. Я обновил свой вопрос с помощью build.gradle, возможно, есть проблема.

nikolardlvc 19.06.2024 22:29

Это может быть другая цепочка фильтров в конфигурации Java или отсутствие @RestController в классе, содержащем @GetMapping(path = "/public/info"), или что-то еще, чего я не вижу в вашем коде. Поскольку вы, похоже, не готовы поделиться воспроизводимым образцом, вам придется начать с того, что я предоставил, и постепенно изменять его.

ch4mp 19.06.2024 23:30

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