试图在Rails中编写用于用户名验证的REGEX

时间:2014-11-13 02:33:40

标签: ruby-on-rails ruby regex

我试图在Ruby(Rails)中编写正则表达式,以便用户名的字符只包含数字和字母(也没有空格)。

我有这个正则表达式/^[a-zA-Z0-9]+$/,但它似乎没有工作,我在Rails中得到错误,说"提供的正则表达式使用多行锚点(^或$ ),这可能带来安全风险。您的意思是使用\ A和\ z,还是忘记添加:multiline =>真正的选择?"

我的user.rb模型中此实现的完整代码是:

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_USERNAME_REGEX = /^[a-zA-Z0-9]+$/
  validates :username, presence: true, length: { maximum: 20 },
                                    format: { with: VALID_USERNAME_REGEX },
                                    uniqueness: { case_sensitive: false }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                format: { with: VALID_EMAIL_REGEX },
                uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, length: { minimum: 6 }
end

我做错了什么以及如何修复此正则表达式以使其仅对数字和字母有效且没有空格?感谢。

2 个答案:

答案 0 :(得分:9)

简短回答:改为使用/\A[a-zA-Z0-9]+\z/(因为VALID_EMAIL_REGEX正在使用)。

答案很长:^$锚点会匹配字符串中的开头和结尾。这意味着如果您的字符串由多行字母数字字符组成,则它们将匹配:

/^[a-zA-Z0-9]+$/ =~ "Ana\nBob\nClara\nDaniel"  #=> 0 (matches)

另一方面,\A\z将匹配字符串的开头和结尾,因此可以防止发送多行字符串的用户可能受到攻击(就像前面的例子一样)。

/\A[a-zA-Z0-9]+\z/ =~ "Ana\nBob\nClara\nDaniel"  #=> nil (doesn't match)
/\A[a-zA-Z0-9]+\z/ =~ "Erika"                    #=> 0   (matches)

答案 1 :(得分:2)

您只需按照错误消息操作即可。将^(行锚的开头)替换为\A(字符串锚点的开头),将$(行尾锚点)替换为\z(字符串锚点结束)。除此之外,你的正则表达式按原样运行。

\A[a-zA-Z0-9]+\z

Rails存在此安全问题,因为与某些语言不同,^$仅匹配单行的开头/结尾,而不是整个字符串。

这说明了这种可能的利用的一个例子:

str = "malicious_code()\naValidUsername"
str.match(/^[a-zA-Z0-9]+$/) # => #<MatchData "aValidUsername">