Grails 3 CSRF 保护

Posted

技术标签:

【中文标题】Grails 3 CSRF 保护【英文标题】:Grails 3 CSRF protection 【发布时间】:2016-07-04 11:54:00 【问题描述】:

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

【问题讨论】:

【参考方案1】:

您可以使用

标签来实现它:

示例:

<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>

【讨论】:

是的,但是在后端你总是应该使用 withForm 方法,这是一个丑陋的解决方案。最好的选择是使用 spring security 中的 CrsfFilter,我设法设置了它,现在它工作正常,但感谢您的回复 :) @enzo 你能分享你的配置吗?也许通过提交它作为这个问题的答案?将不胜感激! @EdJ 看到我上面的回答,有什么问题可以问我。 @enzo 一个问题朋友:我的项目中有多个表单。我应该在 main.gsp 中添加: $(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); ); );【参考方案2】:

为了保护 csrf,我重用了 org.springframework.security.web.csrf.CsrfFilter。您需要在 grails resouces.groovy 中定义新的 bean(参见下面的片段 - csrfFilter bean)。您可以定义自己的 accessDeniedHandlerrequireCsrfProtectionMatcher。这是来自 resources.groovy 的 sn-p:

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 的 sn-p(我正在使用 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 令牌。

【讨论】:

您介意分享一个自定义 accessDeniedHandlerrequireCsrfProtectionMatcher 类的示例吗? 旧线程,但如果有帮助,请参阅:***.com/questions/48307781/…***.com/questions/31098323/…

以上是关于Grails 3 CSRF 保护的主要内容,如果未能解决你的问题,请参考以下文章

CSRF 保护的真正用途是啥?

Rails 3.2 - 为控制器操作禁用 CSRF 保护

CSRF-跨域访问保护

元标记中带有令牌的 CSRF 保护 - 为啥不能被盗?

如何保护 Grails 中的所有 REST 请求和响应

Grails + 保护应用程序