Redmine插件中注册XML导入路由需在config/routes.rb添加POST路由并映射到自定义控制器;控制器须继承ApplicationController、跳过CSRF校验、强制校验登录与项目权限;解析XML时禁用外部实体、限制字段与长度、白名单过滤;创建任务应避免create!,改用save(validate: false)配合手动校验和事务包裹;前端需用FormData提交并携带authenticity_token,curl测试须用-F参数;权限上下文(如@project)必须显式传递,防止自定义字段等依赖丢失。

Redmine插件中如何注册XML导入路由和控制器
XML任务导入不是Redmine原生功能,必须通过插件新增控制器处理上传与解析。关键在于让Redmine识别你的路由,且不被权限系统拦截。
- 在插件的
config/routes.rb中添加资源路由,例如:match 'projects/:project_id/import_tasks_from_xml' => 'import_tasks_from_xml#create', :via => [:post], :as => 'import_tasks_from_xml'
- 控制器需继承
ApplicationController,并显式声明跳过CSRF保护(因为XML上传常由外部脚本发起):skip_before_action :verify_authenticity_token, only: [:create]
- 必须调用
require_login和find_project(或手动校验项目权限),否则普通用户可越权导入到任意项目
如何安全解析上传的XML并映射到Redmine Issue模型
直接用 Nokogiri::XML 解析用户上传的XML存在XXE和内存爆炸风险,不能无过滤加载外部实体或超大文档。
- 强制设置解析选项禁用外部实体:
doc = Nokogiri::XML(params[:xml_file].read) do |config| config.noent.noenc.noblanks end
- 只允许白名单字段:如
、、,忽略所有未知节点 - 对每个字段做长度限制(如
subject截断至 255 字符),防止数据库溢出或日志刷屏 - 用
Project.find_by_identifier而非params[:project_id]直接查库,避免整数ID被伪造为SQL注入载体
为什么用 Issue.create! 容易失败,该用什么替代
create! 会抛出异常中断整个导入流程,而XML通常含多条任务——一条失败不该导致全部回滚,且错误信息需返回给前端供排查。
网趣购物系统静态版支持网站一键静态生成,采用动态进度条模式生成静态,生成过程更加清晰明确,商品管理上增加淘宝数据包导入功能,与淘宝数据同步更新!采用领先的AJAX+XML相融技术,速度更快更高效!系统进行了大量的实用性更新,如优化核心算法、增加商品图片批量上传、谷歌地图浏览插入等,静态版独特的生成算法技术使静态生成过程可随意掌控,从而可以大大减轻服务器的负担,结合多种强大的SEO优化方式于一体,使
- 改用
Issue.new(...).save(validate: false)配合手动校验,避开Redmine默认的自定义字段/工作流校验(这些在校验阶段可能依赖未初始化的上下文) - 对必填字段(如
subject,project_id,author_id)先做空值检查,缺失时记录警告而非报错 - 用
issue.init_journal(User.current)显式初始化日志,否则导入的任务不会出现在“活动”流里 - 批量创建后调用
Issue.transaction { ... }包裹,但不要把整个XML解析塞进去——Nokogiri对象无法跨事务序列化
前端表单和CSRF绕过时的实际兼容问题
浏览器表单无法直接提交XML文件到Redmine插件接口,常见做法是用JavaScript构造FormData,但这会触发CSRF校验失败,除非后端已跳过。
- 表单必须包含
authenticity_token字段,即使后端跳过了验证,Rails中间件仍会尝试读取它;漏掉会导致422响应 - XML文件字段名需与控制器中
params[:xml_file]一致,建议前端用FormData.append('xml_file', file) - 若用curl测试,注意加
-H "Content-Type: multipart/form-data"无效——multipart边界由浏览器自动生成,应让curl自动推导:curl -F "xml_file=@tasks.xml" -F "authenticity_token=..." http://localhost:3000/projects/demo/import_tasks_from_xml
available_custom_fields 依赖当前 @project 实例,而这个实例在后台线程或异步任务中容易丢失。别假设“只要进了控制器就万事大吉”。









