【问题标题】:Testing Spring Controller POST method after adding Spring Security on Kotlin在 Kotlin 上添加 Spring Security 后测试 Spring Controller POST 方法
【发布时间】:2018-08-10 18:19:10
【问题描述】:

我正在使用 Kotlin 开发一个 Spring Boot 应用程序。 我最近添加了 Spring Security 作为依赖项,现在我无法再测试我的控制器了。

这是我的控制器:

@RestController
@RequestMapping("/users", produces = [MediaType.APPLICATION_JSON_UTF8_VALUE])
class UserController {
    @Autowired
    lateinit var userService: UserService

    @PostMapping
    fun addUser(@Valid @RequestBody user: User): ResponseEntity<PostUserResponse> {
        userService.addUser(user)
        return ResponseEntity.status(HttpStatus.CREATED).body(PostUserResponse())
    }

    @GetMapping("user/{login}")
    fun getUserByLogin(@PathVariable login: String): ResponseEntity<User> {
        val user = userService.getUserByLogin(login)
        return ResponseEntity.status(HttpStatus.OK).body(user)
    }

    @ExceptionHandler(NoSuchElementException::class)
    fun failedToRetrieveById(exception: NoSuchElementException): ResponseEntity<UserNotFoundResponse> {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UserNotFoundResponse())
    }
}

这是我的测试课:

@ExtendWith(SpringExtension::class)
@WebMvcTest(controllers = [UserController::class])
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class UserControllerTest {
    @MockBean
    private lateinit var userService: UserService

    @Autowired
    private lateinit var context: WebApplicationContext

    private lateinit var mvc : MockMvc

    val login = "test@test.test"
    val password = "password"
    val user = User(login = login, password = password)

    @BeforeAll
    fun setup () {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply<DefaultMockMvcBuilder>(springSecurity())
                .build()
    }

    @Test
    fun `Sending POST to the users endpoint with a valid json creates a new user`() {
        val payload = mapOf(
                "login" to login,
                "password" to password
        )
        Mockito.`when`(userService.addUser(user))
                .thenReturn(user)


        mvc.perform(MockMvcRequestBuilders.post("/users")
                .with(csrf().asHeader())
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(JSONObject(payload).toString()))
                .andExpect(MockMvcResultMatchers.status().isCreated)
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8))
    }
}

我的代码模仿了可以在此处找到的示例: https://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#test-mockmvc-smmrpp

但回复的 HTTP 代码仍然是 401。

有趣的是,删除该行:

.with(csrf().asHeader())

让服务器回复 403 而不是 401。

我的安全配置基本上是“空白”。我没有指定任何限制,因此根据文档,唯一的问题应该是提供有效的 CSRF 令牌。

@Configuration
@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
    override fun configure (httpSecurity: HttpSecurity) {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/*")
                .permitAll()
    }
}

如何生成有效请求?

【问题讨论】:

    标签: spring testing spring-security kotlin controller


    【解决方案1】:

    这是一个复杂的问题,答案取决于您的安全配置。

    但一般情况下,您应该包含spring-security-test 依赖项,然后this documentation 应该可以帮助您走得更远。

    【讨论】:

    • 感谢您的回复。我在问题中添加了我的安全配置(目前非常基本)。根据我对文档的理解,CSRF 令牌应该是使请求有效的唯一要求。
    • 401 表示请求是由未经身份验证的用户发出的。要更改此尝试添加:perform(post("/users").with(user("user")))。这会将用户添加到安全上下文中,并且请求应该传递给控制器​​。
    • 成功了。我没明白你必须默认指定一个用户
    猜你喜欢
    • 2013-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 2013-02-10
    • 2020-09-26
    • 2020-02-28
    相关资源
    最近更新 更多