如何为PlayFramework 1.7所有表单自动注入#{authenticityToken /}
自动为PlayFramework 1.7所有表单注入CSRF令牌的方案
针对你的场景,有两种实用的自动注入方式,无需手动修改上百个表单:
方案一:重写内置form模板标签
Play 1.x允许自定义模板标签覆盖内置标签,原有表单代码无需改动即可自动带上令牌:
- 在项目的
app/views/目录下新建tags文件夹(若不存在) - 在
tags目录中创建form.tag文件,内容如下:
#{form @${action}, id:'${id}', class:'${class}', method:'${method ?: 'POST'}'} #{authenticityToken /} ${_raw} #{/form}
这个自定义标签会先渲染内置form标签,自动插入#{authenticityToken /}后,再将原表单内容(${_raw})填充进去。后续所有使用#{form}的地方都会自动携带CSRF令牌。
方案二:用模板拦截器自动修改输出
如果不想改动模板标签,可通过拦截器在模板渲染后自动往POST表单插入令牌:
- 创建Java类实现模板拦截器:
import play.mvc.Filter; import play.mvc.Http; import play.templates.Template; import play.templates.TemplateInterceptor; public class CSRFTokenInjector extends Filter implements TemplateInterceptor { @Override public String onRender(Template template, String renderedContent) { // 从会话中获取CSRF令牌 String token = play.mvc.Controller.session.get("authenticityToken"); if (token == null) { return renderedContent; } // 生成隐藏的令牌输入框 String tokenInput = String.format("<input type=\"hidden\" name=\"authenticityToken\" value=\"%s\" />", token); // 给所有POST表单插入令牌(含显式指定method="POST"和默认POST的表单) renderedContent = renderedContent.replaceAll( "<form(.*?)method=\"POST\"(.*?)>", "<form$1method=\"POST\"$2>" + tokenInput ); renderedContent = renderedContent.replaceAll( "<form(?!.*?method=)(.*?)>", "<form$1method=\"POST\">" + tokenInput ); return renderedContent; } @Override public void doFilter(Http.Request request, Http.Response response, Http.FilterChain chain) throws Exception { chain.next(request, response); } }
- 在
conf/application.conf中添加配置启用拦截器:
play.template.interceptors=CSRFTokenInjector
这种方式无需修改任何模板代码,拦截器会在模板渲染完成后自动处理所有POST表单并插入令牌。注意正则替换对不规范HTML可能存在兼容问题,适合大部分标准表单场景。
注意事项
- 测试时可查看页面源码,确认令牌是否正确注入
- 若项目存在GET表单(不建议用GET执行修改操作),需调整方案二的正则规则避免误注入
- 确保后端已正确配置
authenticityToken的验证逻辑,避免注入令牌却未验证的情况
内容的提问来源于stack exchange,提问作者jasraj bedi
相关产品推荐
相关产品推荐

