簡體   English   中英

使用Spring Security時如何在速度宏中獲取CSRF令牌

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM