Spring 引导 Groovy 模板未将 _csrf 添加到模型
Spring Boot Groovy Templates Not Adding _csrf to model
我有一个非常简单的 Spring 引导应用程序,它由一个主要的 Application.java(使用默认的主要方法)、一个 MainController(它有一个到 /login 的 requestMapping)和一个 SecurityConfig 组成(主要是默认值)。
我的问题是 Groovy 模板中的 _csrf 支持。 FreeMarker 一切正常,但是当我切换到 GroovyTemplates 时,_csrf 参数没有被放入模型中。
Groovy 模板中是否存在错误,我必须手动执行某些操作才能获取令牌,或者是否缺少某些配置步骤(尽管我不知道为什么会起作用对于 FreeMarker) ?
更新:
我在 login.tpl(Groovy 模板)上打印了 this.properties(HashMap):
{class=class login, out=java.io.BufferedWriter@5e2aead3, model={error=Optional.empty, org.springframework.validation.BindingResult.error=org.springframework.validation.BeanPropertyBindingResult: 0 errors, spring=org.springframework.web.servlet.support.RequestContext@1d99fb33, springMacroRequestContext=org.springframework.web.servlet.support.RequestContext@7fcc5c78}}
属性映射中的模型键包含参数
我使用以下方法在控制器操作中添加了错误:
@RequestMapping(value="/login", method = RequestMethod.GET)
public ModelAndView login(@RequestParam Optional<String> error) {
return new ModelAndView("views/login", "error", error);
}
当使用 GroovyMarkupView
和 GroovyMarkupViewResolver
时,视图的属性仅包含模型中可用的属性(有些是为 Groovy 添加的)。
要包含请求属性,请将 GroovyMarkupViewResolver
的 exposeRequestAttributes
属性 设置为 true
。理想情况下,这是通过在 application.properties
.
中设置以下 属性 来完成的
spring.groovy.template.exposeRequestAttributes=true
但是由于 this issue 目前无法实现。
要解决它,请创建一个 BeanPostProcessor
,它检查传入的 bean 是否是 GroovyMarkupViewResolver
(如果您想要更通用的方法,则为 AbstractTemplateViewResolver
)。如果是这样,请将 exposeRequestAttributes
设置为 true。
public class TemplateViewResolverPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instance GroovyMarkupViewResolver) {
((GroovyMarkupViewResolver) bean).setExposeRequestAttributes(true);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
完成后 CsfrToken
可用键 _csfr
,请注意这是实际的 CsfrToken
。
另一个解决方案是创建一个 HandlerInterceptor
实现 postHandle
方法并将 _csfr
属性 添加到模型中。这样你就可以简单地添加令牌的值而不是实际的令牌本身。这将适用于任何使用的视图技术。
public class CsrfAddingInterceptor extends HandlerInterceptorAdapter {
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mav) throws Exception {
CsrfToken token = (CsrfToken) req.getAttribute(CsrfToken.class.getName())
if (token != null) {
mav.addAttribute(token.getParameterName(), token.getToken());
}
}
}
然后将其添加为拦截器,您将获得可用的值。
所以处理这个问题的破解方法是手动将 _csrf 属性添加到控制器中的模型。例如:
model.addAttribute( "_csrf", request.getAttribute("_csrf") );
如果您的服务器上有很多视图,我不建议这样做。我建议您遵循@M-Deinnum 的其中一个选项。但是,为了快速测试,这是可行的。
我有一个非常简单的 Spring 引导应用程序,它由一个主要的 Application.java(使用默认的主要方法)、一个 MainController(它有一个到 /login 的 requestMapping)和一个 SecurityConfig 组成(主要是默认值)。
我的问题是 Groovy 模板中的 _csrf 支持。 FreeMarker 一切正常,但是当我切换到 GroovyTemplates 时,_csrf 参数没有被放入模型中。
Groovy 模板中是否存在错误,我必须手动执行某些操作才能获取令牌,或者是否缺少某些配置步骤(尽管我不知道为什么会起作用对于 FreeMarker) ?
更新:
我在 login.tpl(Groovy 模板)上打印了 this.properties(HashMap):
{class=class login, out=java.io.BufferedWriter@5e2aead3, model={error=Optional.empty, org.springframework.validation.BindingResult.error=org.springframework.validation.BeanPropertyBindingResult: 0 errors, spring=org.springframework.web.servlet.support.RequestContext@1d99fb33, springMacroRequestContext=org.springframework.web.servlet.support.RequestContext@7fcc5c78}}
属性映射中的模型键包含参数
我使用以下方法在控制器操作中添加了错误:
@RequestMapping(value="/login", method = RequestMethod.GET)
public ModelAndView login(@RequestParam Optional<String> error) {
return new ModelAndView("views/login", "error", error);
}
当使用 GroovyMarkupView
和 GroovyMarkupViewResolver
时,视图的属性仅包含模型中可用的属性(有些是为 Groovy 添加的)。
要包含请求属性,请将 GroovyMarkupViewResolver
的 exposeRequestAttributes
属性 设置为 true
。理想情况下,这是通过在 application.properties
.
spring.groovy.template.exposeRequestAttributes=true
但是由于 this issue 目前无法实现。
要解决它,请创建一个 BeanPostProcessor
,它检查传入的 bean 是否是 GroovyMarkupViewResolver
(如果您想要更通用的方法,则为 AbstractTemplateViewResolver
)。如果是这样,请将 exposeRequestAttributes
设置为 true。
public class TemplateViewResolverPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instance GroovyMarkupViewResolver) {
((GroovyMarkupViewResolver) bean).setExposeRequestAttributes(true);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
完成后 CsfrToken
可用键 _csfr
,请注意这是实际的 CsfrToken
。
另一个解决方案是创建一个 HandlerInterceptor
实现 postHandle
方法并将 _csfr
属性 添加到模型中。这样你就可以简单地添加令牌的值而不是实际的令牌本身。这将适用于任何使用的视图技术。
public class CsrfAddingInterceptor extends HandlerInterceptorAdapter {
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mav) throws Exception {
CsrfToken token = (CsrfToken) req.getAttribute(CsrfToken.class.getName())
if (token != null) {
mav.addAttribute(token.getParameterName(), token.getToken());
}
}
}
然后将其添加为拦截器,您将获得可用的值。
所以处理这个问题的破解方法是手动将 _csrf 属性添加到控制器中的模型。例如:
model.addAttribute( "_csrf", request.getAttribute("_csrf") );
如果您的服务器上有很多视图,我不建议这样做。我建议您遵循@M-Deinnum 的其中一个选项。但是,为了快速测试,这是可行的。