在 RoR4中带有验证的正则表达式

有以下代码:

class Product < ActiveRecord::Base
validates :title, :description, :image_url, presence: true
validates :price, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true
validates :image_url, allow_blank: true, format: {
with: %r{\.(gif|jpg|png)$}i,
message: 'URL must point to GIT/JPG/PNG pictures'
}
end

它可以工作,但是当我尝试使用“ rake test”测试它时,我会捕捉到以下信息:

rake aborted!
The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?

这是什么意思? 我该怎么补救?

32627 次浏览

^$是起始 和结束 锚。而 \A\z是永久起始 字符串和结束 字符串锚。
看到区别了吗:

string = "abcde\nzzzz"
# => "abcde\nzzzz"


/^abcde$/ === string
# => true


/\Aabcde\z/ === string
# => false

因此 Rails 告诉您,“您确定要使用 ^$吗?你不想改用 \A\z吗?”

还有更多的在轨安全问题,生成这个警告 给你

由于验证规则容易受到 javascript 注入的影响,因此会引发此警告。

在您的情况下,\.(gif|jpg|png)$匹配到行的末尾。因此,您的规则将验证这个值 pic.png\nalert(1);为 true:

"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)$/i
# => true


"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)\z/i
# => false

阅读下列动作:

这个警告告诉您,下面这样的字符串将通过验证,但它可能不是您想要的:

test = "image.gif\nthis is not an image"
re = /\.(gif|jpg|png)$/i
re.match(test) #=> #<MatchData ".gif" 1:"gif">

^$都匹配任何行的开始/结束,而不匹配字符串的开始/结束。\A\z分别匹配完整字符串的开始和结束。

re = /\.(gif|jpg|png)\z/i
re.match(test) #=> nil

警告的第二部分(“或者忘记添加: multiline = > true 选项”)告诉您,如果您确实想要 ^$的行为,您可以通过传递 :multiline选项来压制警告。

Regexp 问题不在设计中,而是存在于 config/initializer/devise.rb 中。更改:

# Regex to use to validate the email address
config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i

致:

# Regex to use to validate the email address
config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\Z/i

如果 Ruby 希望看到的是 \z而不是 $符号符号,为了安全起见,你需要把它给他,那么代码应该是这样的:

validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}