Grails 3 CSRF保护

时间:2016-03-17 21:49:14

标签: grails spring-security csrf csrf-protection grails-3.0

是否可以使用spring-security插件在grails3 app中配置CSRF保护,除了grails表单的useToken属性之外我找不到任何东西,然后在控制器内调用withForm。但这实际上不是一个非常灵活的解决方案。我喜欢使用像here

这样的过滤器

2 个答案:

答案 0 :(得分:10)

对于csrf保护,我重复使用 org.springframework.security.web.csrf.CsrfFilter 。您需要在grails resouces.groovy中定义新bean(请参阅下面的snipet - csrfFilter bean)。您可以定义自己的 accessDeniedHandler requireCsrfProtectionMatcher 。这是resources.groovy的片段:

csrfFilter(CsrfFilter, new HttpSessionCsrfTokenRepository()) {
    accessDeniedHandler = ref('fnAccessDeniedHandler')
    requireCsrfProtectionMatcher = ref('fnRequireCsrfProtectionMatcher')
}

现在在Bootstrap.groovy中将此过滤器添加到过滤器链中:

 SpringSecurityUtils.clientRegisterFilter('csrfFilter',    SecurityFilterPosition.LAST.order + 10)

现在,在您的主要布局GSP中添加以下标记,以在每个页面上添加csrf标记:

<meta name="_csrf" content="${_csrf?.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf?.headerName}"/>

所以现在csrf令牌出现在你应用的每个页面上,你可以将它用于每个ajax请求,例如(来自application.js的片段(我使用的是grails 3)):

$(function () {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });
});

对于每个jquery ajax请求,我们现在都在发送csrf令牌。

答案 1 :(得分:2)

您可以使用&lt; g:form&gt; 标记来实现它:

示例:

<g:form useToken="true" uri="/logout">

文档: http://grails.github.io/grails-doc/latest/guide/single.html#formtokens

就我而言,我使用的是Spring代码,所以,另外,我应该在表单中手动添加一个_csrf隐藏字段。

<g:form useToken="true" uri="/logout">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <input type="submit">Logout</input>
</g:form>

<强>结果:

<form action="/nacho/logout" method="post" >

    <!-- this two lines are added automatically by Grails -->
    <input type="hidden" name="SYNCHRONIZER_TOKEN" value="883a1037-a2c9-4997-8254-e59da6303494" id="SYNCHRONIZER_TOKEN" />
    <input type="hidden" name="SYNCHRONIZER_URI" value="/nacho/userInfo" id="SYNCHRONIZER_URI" />

    <!-- this line was added by myself, but, using the ${_csrf} variable -->
    <input type="hidden" name="_csrf" value="0928f13c-02aa-4122-8ebe-a1239855a85b"/>

    <input type="submit">Logout</input>
</form>