ActiveAdmin中配置了必填、类型校验的无效表单为何仍可提交?
问题根因
当前实现能绕过校验直接提交的核心原因有四点:
- 没有在User模型层配置对应字段的校验规则,仅在视图层添加的HTML5标记没有服务端拦截逻辑,只要用户绕开前端校验(比如抓包直接发送请求),后端会直接把不合规数据存入数据库
- ActiveAdmin表单底层依赖的Formtastic库,前端校验逻辑是自动读取模型上的校验定义生成的,手动在input参数里写的
required: true、input_html配置,没有模型校验做支撑的话,往往无法正确触发校验提示 - 部分版本的ActiveAdmin会默认给提交按钮加上
formnovalidate属性,直接全局禁用整个表单的HTML5原生校验,就算给input写了required标记,也不会触发前端拦截 - 现有代码的
permit_params只放开了email字段的参数白名单,first_name、last_name的提交值会被Rails强参数过滤,就算填写了也不会正常入库
修复步骤
1. 补全模型层兜底校验
这是最核心的保障,不管前端校验是否生效,服务端必须对不合规输入做拦截,在对应模型中添加校验规则:
# app/models/user.rb class User < ApplicationRecord # 校验邮箱必填 validates :email, presence: true # 校验邮箱格式符合通用规则 validates :email, format: { with: URI::MailTo::EMAIL_REGEXP, message: "请输入合法的邮箱地址" } end
2. 调整ActiveAdmin表单配置
- 把缺失的字段加入
permit_params白名单 - 删掉手动冗余的input属性配置,让Formtastic根据模型校验自动生成对应的前端校验标记
- 自定义提交按钮,去掉默认携带的
formnovalidate属性,恢复HTML5原生校验的触发能力
调整后的完整代码:
ActiveAdmin.register User do actions :all, except: [:destroy, :edit] # 补全所有可提交字段的强参数白名单 permit_params :email, :first_name, :last_name form do |f| f.semantic_errors f.inputs 'Invite a new user' do # 模型定义校验后,自动生成email类型、必填标记 f.input :email f.input :first_name f.input :last_name end # 自定义提交按钮,移除禁用校验的属性 f.actions do f.action :submit, button_html: { formnovalidate: false } f.cancel_link end end end
调整后效果
- 留空必填邮箱时,前端会直接弹出必填提示,无法提交
- 在邮箱输入框填写数字等非邮箱格式内容时,前端会弹出格式校验提示
- 就算用户通过技术手段绕开前端校验,服务端检测到不合规数据后,会通过
f.semantic_errors展示具体错误,阻止数据入库
内容的提问来源于stack exchange,提问作者Nathan Gouy
相关产品推荐
相关产品推荐

