spring-boot - Spring Security @WithMockUser doesn't seem to work with state changing verbs (post, put..)
问题描述
Here is my setup:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup", "/health").permitAll()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/login")
.permitAll()
...
Test class:
@ExtendWith(SpringExtension.class)
@WebMvcTest
@WithMockUser
class ApiControllerTest {
...
@WithMockUser
works fine with below GET:
mockMvc.perform(get("/api/book/{id}", id))
.andExpect(status().isOk())
...
but not with POST:
mockMvc.perform(post("/api/book")
.contentType(MediaType.APPLICATION_JSON)
.content(payload))
.andExpect(status().isCreated())
...
When I look into the logs for MockHttpServletResponse, I notice the response is giving a redirect to login page, as follows:
MockHttpServletResponse:
Status = 302
Error message = null
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY", Location:"/login"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = /login
Cookies = []
I know that @WithMockUser
provides good amount of defaults for mocking user authentication. Why it is not working for stateful API request?
解决方案
默认情况下,Spring Security 保护您免受跨站点请求伪造。
如果你不想要它,你必须在你的配置中主动禁用它。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
...
幸运的是你没有这样做,这样做是不安全的。
但是因此,每次执行 a 时都需要提供一个 csrf-token POST
,在您的测试中也是如此!
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
...
mockMvc.perform(post("/api/book")
.with(csrf()) // <--- missing in your test
.contentType(MediaType.APPLICATION_JSON)
.content(payload))
.andExpect(status().isCreated());
现在你的测试应该可以工作了。
推荐阅读
- c# - C# 卡在 db call 甚至 oracle 在大约 30 分钟后自动清除会话
- php - 更改 pchart 分隔符
- python - 阅读outlook邮箱,连续收到两封相同主题的邮件
- scala - 当您使用 Seq(1,2,3) 创建 Seq 对象时会发生什么?
- php - 如何使用 php 压缩/降低 base64 图像的质量?
- java - 尝试使用 replaceFirst 将值添加到查询字符串参数字段
- python - 搜索 pandas.Series 中不存在的标签时出现 KeyError
- mysql - 单个 mysql 查询:使表的 NULL 值和数据库中的列
- r - For 循环不适用于 If 语句:条件的长度 > 1 并且只会使用第一个元素
- angular - 使用Angular显示外键值而不是键