Весенний WebMvcTest с возвратом поста 403 - PullRequest
0 голосов
/ 25 октября 2018

Мне интересно, где проблема с моим кодом, каждый раз, когда я запускаю пост-тест (независимо от того, на какой контроллер он нацелен или метод), я возвращаю ошибку 403, когда в некоторых случаях я ожидаю 401, ив других ответ 200 (с аутентификацией).

Это фрагмент моего контроллера:

@RestController
@CrossOrigin("*")
@RequestMapping("/user")
class UserController @Autowired constructor(val userRepository: UserRepository) {
    @PostMapping("/create")
    fun addUser(@RequestBody user: User): ResponseEntity<User> {
        return ResponseEntity.ok(userRepository.save(user))
    }
}

И мой юнит-тест, нацеленный на этот контроллер

@RunWith(SpringRunner::class)
@WebMvcTest(UserController::class)
class UserControllerTests {
    @Autowired
    val mvc: MockMvc? = null

    @MockBean
    val repository: UserRepository? = null

    val userCollection = mutableListOf<BioRiskUser>()

    @Test
    fun testAddUserNoAuth() {
        val user = BioRiskUser(
                0L,
                "user",
                "password",
                mutableListOf(Role(
                    0L,
                    "administrator"
                )))
        repository!!
        `when`(repository.save(user)).thenReturn(createUser(user))
        mvc!!
        mvc.perform(post("/create"))
                .andExpect(status().isUnauthorized)
    }

    private fun createUser(user: BioRiskUser): BioRiskUser? {
        user.id=userCollection.count().toLong()
        userCollection.add(user)
        return user
    }
}

Чтоя пропускаю?

В соответствии с запросом, моя конфигурация безопасности ...

@Configuration
@EnableWebSecurity
class SecurityConfig(private val userRepository: UserRepository, private val userDetailsService: UserDetailsService) : WebSecurityConfigurerAdapter() {
    @Bean
    override fun authenticationManagerBean(): AuthenticationManager {
        return super.authenticationManagerBean()
    }

    override fun configure(auth: AuthenticationManagerBuilder) {
        auth.authenticationProvider(authProvider())
    }

    override fun configure(http: HttpSecurity) {
        http
            .csrf().disable()
            .cors()
            .and()
            .httpBasic()
            .realmName("App Realm")
            .and()
            .authorizeRequests()
            .antMatchers("/img/*", "/error", "/favicon.ico", "/doc")
            .anonymous()
            .anyRequest().authenticated()
            .and()
            .logout()
            .invalidateHttpSession(true)
            .clearAuthentication(true)
            .logoutSuccessUrl("/user")
            .permitAll()
    }

    @Bean
    fun authProvider(): DaoAuthenticationProvider {
        val authProvider = CustomAuthProvider(userRepository)
        authProvider.setUserDetailsService(userDetailsService)
        authProvider.setPasswordEncoder(encoder())
        return authProvider
    }
}

и поставщик аутентификации

class CustomAuthProvider constructor(val userRepository: UserRepository) : DaoAuthenticationProvider() {
    override fun authenticate(authentication: Authentication?): Authentication {
        authentication!!
        val user = userRepository.findByUsername(authentication.name)
        if (!user.isPresent) {
            throw BadCredentialsException("Invalid username or password")
        }
        val result = super.authenticate(authentication)
        return UsernamePasswordAuthenticationToken(user, result.credentials, result.authorities)
    }


    override fun supports(authentication: Class<*>?): Boolean {
        return authentication?.equals(UsernamePasswordAuthenticationToken::class.java) ?: false
    }
}

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Вот проблема:

override fun configure(http: HttpSecurity) {
    http
        .csrf().disable()
        .cors()
        .and()
        .httpBasic()
        .realmName("App Realm")
        .and()
        .authorizeRequests()
        .antMatchers("/img/*", "/error", "/favicon.ico", "/doc")
        .anonymous()
        .anyRequest().authenticated()
        .and()
        .logout()
        .invalidateHttpSession(true)
        .clearAuthentication(true)
        .logoutSuccessUrl("/user")
        .permitAll()
}

Более конкретно здесь:

.anyRequest().authenticated()

Вы требуете, чтобы каждый запрос был аутентифицирован, поэтому вы получаете 403.

Этот урок хорошо объясняет, как выполнять тестирование с помощью фиктивного пользователя.

Самый простой способ - создать что-то вроде этого:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class SecuredControllerRestTemplateIntegrationTest {

    @Autowired
    private val template: TestRestTemplate

    @Test
    fun createUser(): Unit {
        val result = template.withBasicAuth("username", "password")
          .postForObject("/user/create", HttpEntity(User(...)), User.class)
        assertEquals(HttpStatus.OK, result.getStatusCode())
    }
}
0 голосов
/ 25 октября 2018

Вам нужно добавить @ContextConfiguration(classes=SecurityConfig.class) в начало класса UserControllerTests после аннотации @WebMvcTest(UserController::class).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...