[英]How to obtain csrf token in a velocity macro when using spring security
我試圖為啟用了Spring Web Security的應用程序創建自定義登錄屏幕,但是我無法弄清楚如何將csrf令牌傳遞給Velocity(不,目前我不能使用JSP)。
該模型如下所示:
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username or password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("login");
return model;
}
速度模板的相關部分如下所示(摘自jsp示例):
<form name='loginForm' action="/login" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
當然, ${_csrf.parameterName}
和${_csrf.token}
變量為空,因此僅在禁用csrf保護的情況下才有效。 所以我的主要問題是:如何將它們填充到模型中(或其他任何地方)?
我已經找到了解決方案,要點是csrf令牌是由CsrfFilter注入到HttpServletRequest中的,您可以通過向處理請求映射的方法中添加HttpServletRequest參數來獲取HttpServletRequest對象。
因此,需要完成的更改是:
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout,
HttpServletRequest request
){
...
CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrfToken != null) {
model.addObject("_csrf",csrfToken);
}
...
只是分享一點,我最初是使用@P.Péter的解決方案開始的。 但是隨着我的應用程序具有如此多的形式,我認為對於需要保護其免受csrf入侵的每種形式,都使用該代碼段太麻煩了,所以這就是我要做的,因此我不必在整個應用程序中重復。
@ControllerAdvice
public class CsrfControllerAdvice {
@Autowired
private HttpServletRequest request;
@ModelAttribute("_csrf")
public CsrfToken appendCSRFToken(){
//HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return (CsrfToken) request.getAttribute(CsrfToken.class.getName());
}
}
要點 -這個想法是使用@ControllerAdvice
,它在進入任何Spring Controller時都會被調用,並使用@ModelAttribute("<attribute-name>")
批注將CsrfToken附加到結果視圖。
注意1-此_csrf
模型屬性已附加到所有視圖,因此,如果您想將_csrf
處理限制為選定的URL或視圖,請參見此處的資源,以獲取有關如何執行此操作的非常好的示例。
注意2-注意我如何注釋掉以下行?
//HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
這是因為在我的情況下,Autowired HttpServletRequest
實例足以滿足我的情況。 但是,有些情況可能會保證您使用注釋掉的實例,例如,當您需要從應用程序的某些部分(不一定是請求范圍的)中獲取請求對象時……請參閱此線程在此處指出的@Samit G的答案,以獲取相關信息。更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.