Grails 3 CSRF 保护
Grails 3 CSRF protection
是否可以使用 spring-security 插件在 grails3 应用程序中配置 CSRF 保护,我找不到任何东西,除了 grails 表单的 useToken 属性然后在控制器中调用 withForm。但这实际上并不是一个非常灵活的解决方案。我喜欢像 here
这样的过滤器
您可以使用 标签实现它:
示例:
<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>
为了 csrf 保护,我重新使用了 org.springframework.security.web.csrf.CsrfFilter。您需要在 grails resouces.groovy 中定义新 bean(参见下面的代码片段 - 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 令牌。
是否可以使用 spring-security 插件在 grails3 应用程序中配置 CSRF 保护,我找不到任何东西,除了 grails 表单的 useToken 属性然后在控制器中调用 withForm。但这实际上并不是一个非常灵活的解决方案。我喜欢像 here
这样的过滤器您可以使用
示例:
<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>
为了 csrf 保护,我重新使用了 org.springframework.security.web.csrf.CsrfFilter。您需要在 grails resouces.groovy 中定义新 bean(参见下面的代码片段 - 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 令牌。