问题描述
我在 Spring Boot 项目中添加了基本身份验证,但遇到了一些意外错误。
安全配置类:
@EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Value("${myapp.user}")
private String user;
@Value("${myapp.password}")
private String password;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.antMatcher("/postgres/**")
.authorizeRequests(authorize ->
authorize
.anyRequest()
.hasRole("USER"))
.httpBasic(Customizer.withDefaults())
.csrf().disable();
}
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(user).password(passwordEncoder().encode(password))
.authorities("ROLE_USER");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
我在 build.gradle 文件中添加了 2 个依赖项:
implementation group: 'org.springframework.boot',name: 'spring-boot-starter-web',version: '2.4.4'
implementation group: 'org.springframework.boot',name: 'spring-boot-starter-security',version: '2.4.4'
build.gradle:
dependencies {
developmentOnly "org.springframework.boot:spring-boot-devtools"
implementation "org.springframework.boot:spring-boot-starter-webflux"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.data:spring-data-r2dbc:1.1.4.RELEASE'
implementation 'org.mapstruct:mapstruct:1.3.1.Final'
def springFoxVersion = "3.0.0"
implementation "io.springfox:springfox-boot-starter:$springFoxVersion"
implementation "io.springfox:springfox-swagger2:$springFoxVersion"
implementation "io.springfox:springfox-swagger-ui:$springFoxVersion"
implementation "io.springfox:springfox-spring-webflux:$springFoxVersion"
implementation 'net.logstash.logback:logstash-logback-encoder:6.4'
compileOnly 'org.projectlombok:lombok'
compile 'javax.persistence:javax.persistence-api:2.2'
runtimeOnly 'io.r2dbc:r2dbc-postgresql'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.1.Final'
annotationProcessor 'org.projectlombok:lombok'
testImplementation "org.springframework.boot:spring-boot-starter-test"
testImplementation 'org.springframework.cloud:spring-cloud-starter:2.2.5.RELEASE'
testImplementation "io.projectreactor:reactor-test"
def junitJupiterVersion = "5.4.2"
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitJupiterVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
def testContainersversion = "1.15.0"
testImplementation "org.testcontainers:postgresql:$testContainersversion"
testImplementation "org.testcontainers:r2dbc:$testContainersversion"
testImplementation "org.testcontainers:testcontainers:$testContainersversion"
testImplementation "org.testcontainers:junit-jupiter:$testContainersversion"
testImplementation 'com.google.truth:truth:1.0.1'
def mockitoVersion = "3.5.7"
testImplementation "org.mockito:mockito-core:$mockitoVersion"
testImplementation "org.mockito:mockito-junit-jupiter:$mockitoVersion"
}
还有我的测试课:
@SpringBoottest
@Testcontainers
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@AutoConfigureWebTestClient
class MyApplicationContainerTest {
@Autowired
PostgresController postgresController;
@Autowired
WebTestClient webTestClient;
@Autowired
EventRepository eventRepository;
@DynamicPropertySource
static void registerDynamicProperties(DynamicPropertyRegistry registry) {
registry.add("spring.r2dbc.url",() -> "r2dbc:tc:postgresql:///test?TC_IMAGE_TAG=13.1");
}
@TestConfiguration
static class TestConfig {
@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
final ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
final CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
initializer.setDatabasePopulator(populator);
return initializer;
}
}
@AfterEach
public void afterEach() {
eventRepository.deleteall().block(Duration.ofSeconds(5));
}
@Test
void contextShouldLoad() {
assertthat(postgresController).isNotNull();
}
@Test
void shouldInsertEventsIntoDatabase() {
final Event event = Event.builder()
.userId(1L)
.build();
webTestClient
.post()
.uri("/postgres/save_event")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(Mono.just(event),Event.class)
.exchange()
.expectStatus().isOk()
eventRepository.findAll().take(1).as(StepVerifier::create)
.expectNext(EventEntity.builder()
.userId(1L)
.build())
.verifyComplete();
}
当我这样做时,我已经在工作的测试失败了:
Caused by: org.springframework.beans.factory.NoSuchBeanDeFinitionException: No qualifying bean of type 'org.springframework.test.web.reactive.server.WebTestClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我期待的是某种身份验证错误,而不是 bean。 我能够通过使用不同的测试类注释来绕过这个:
@AutoConfigureWebTestClient
@ComponentScan("mypackage")
@Testcontainers
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@WebFluxTest(value = PostgresController.class)
@ContextConfiguration(classes = {
PostgresFacade.class,PostgresController.class,EventService.class,EventRepository.class,EventMapper.class})
Caused by: org.springframework.beans.factory.support.BeanDeFinitionOverrideException: Invalid bean deFinition with name 'requestDataValueProcessor' org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class
org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.class
这可以通过
解决spring.main.allow-bean-deFinition-overriding=true
以我目前的知识无法修复的错误结束:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'eventRepository' defined in mypackage.repository.EventRepository defined in @EnableR2dbcRepositories declared on MyApp: Cannot resolve reference to bean 'r2dbcDatabaseClient' while setting bean property 'databaseClient'; nested exception is org.springframework.beans.factory.NoSuchBeanDeFinitionException: No bean named 'r2dbcDatabaseClient' available
...
Caused by: org.springframework.beans.factory.NoSuchBeanDeFinitionException: No bean named 'r2dbcDatabaseClient' available
结论
我期待一个身份验证错误,我可以通过诸如 @WithMockUser 注释之类的东西来克服它,但是我遇到了 bean 和依赖项的错误循环。 有人可以帮我指出我犯的错误以及应该怎么做才能正确运行测试吗?
控制器看起来像:
@RestController
@RequestMapping("postgres/")
@Timed
public class PostgresController {
private final PostgresFacade postgresFacade;
@Autowired
public PostgresController(PostgresFacade postgresFacade) {
this.postgresFacade = postgresFacade;
}
@PostMapping(path = "/save_event)
public Mono<EventDto> saveEvent(@RequestBody EventDto event) {
return postgresFacade.saveEvent(event);
}
}
PostgresFacade 只是一个带有@Component 注解的层。映射器、存储库和服务也已正确注释。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)