我使用Freemarker與Spring Boot並進行mvc單元測試。在我的freemarker模板我對CSRF令牌這樣一個隱藏的輸入字段:Spring Boot,Freemarker,MVC單元測試,Csrf
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
然後我也有一個MVC單元測試:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class MvcTests {
@Autowired
WebApplicationContext ctx;
MockMvc mvc;
HttpSessionCsrfTokenRepository httpSessionCsrfTokenRepository;
@Before
public void setUp() throws Exception {
mvc = webAppContextSetup(ctx).build();
httpSessionCsrfTokenRepository = new HttpSessionCsrfTokenRepository();
}
@Test
public void testInValidVoucherNumber() throws Exception {
CsrfToken csrfToken = httpSessionCsrfTokenRepository.generateToken(new MockHttpServletRequest());
mvc.perform(post("/voucher/claim")
.sessionAttr("_csrf.parameterName", "_csrf")
.sessionAttr("_csrf.token", csrfToken.getToken())
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("code", "ABC")
.param("_csrf", csrfToken.getToken()))
.andExpect(status().isOk())
.andExpect(view().name("claim-voucher"))
.andExpect(content().string(containsString("Code is invalid")));
}
}
當我運行單元測試,我得到以下的freemarker錯誤:
testInValidVoucherNumber(MvcTests) Time elapsed: 0.904 sec <<< ERROR!
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> _csrf [in template "claim-voucher.ftl" at line 25, column 34]
----
Tip: If the failing expression is known to be legally refer to something that's null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: ${_csrf.parameterName} [in template "claim-voucher.ftl" at line 25, column 32]
~ Reached through: #nested [in template "layout.ftl" in macro "basic" at line 16, column 9]
這裏是控制器:
@RequestMapping(value = "/voucher/claim", method = RequestMethod.POST)
public String checkVoucherCode(@Valid ClaimVoucherForm claimVoucherForm, Model model) {
//Business logic
}
似乎freemarker無法訪問csrf parameterName和csrf標記。有沒有辦法在不改變控制器的情況下包含csrf信息,或者單元測試是否存在問題?
這很奇怪,我之前使用過thymeleaf,而且我不必將csrf標記添加到html中,然後我切換到Freemarker,因爲thymeleaf給了我一些問題。從那時起,我不得不添加csrf標籤,否則在將表單發佈到服務器時會出現錯誤。 – 2015-02-18 07:58:55
這是因爲Spring的JSP/Thymeleaf窗體標籤自動爲您添加隱藏字段:https://github.com/spring-projects/spring-framework/blob/6062e15572eefa73954a69c109cc90f068486065/spring-webmvc/src/main/java/org/springframework/ web/servlet/tags/form/FormTag.java#L484-L512和https:// github。com/thymeleaf/thymeleaf-spring/blob/2e752f705e7be87ef7d077d90ff822d248d9033b/thymeleaf-spring4/src/main/java/org/thymeleaf/spring4/processor/attr/SpringActionAttrProcessor.java#L96-L122。 – 2015-02-18 09:24:58
謝謝你的工作! – 2015-02-18 14:57:51