【问题标题】:How do I check whether a value in a string is an IP address如何检查字符串中的值是否为 IP 地址
【发布时间】:2011-04-07 19:01:38
【问题描述】:

当我这样做时

ip = request.env["REMOTE_ADDR"]

我得到客户端的IP地址吧。但是如果我想验证变量中的值是否真的是 IP 怎么办? 我该怎么做?

请帮忙。 提前致谢。对不起,如果这个问题被重复,我没有努力找到它......

编辑

IPv6 IP 呢??

【问题讨论】:

标签: ruby-on-rails ruby string ip ipv6


【解决方案1】:

Ruby 已经在标准库中提供了所需的 Regex。 结帐resolv

require "resolv"

"192.168.1.1"   =~ Resolv::IPv4::Regex ? true : false #=> true
"192.168.1.500" =~ Resolv::IPv4::Regex ? true : false #=> false

"ff02::1"    =~ Resolv::IPv6::Regex ? true : false #=> true
"ff02::1::1" =~ Resolv::IPv6::Regex ? true : false #=> false

如果你喜欢它的捷径......

require "resolv"

!!("192.168.1.1"   =~ Resolv::IPv4::Regex) #=> true
!!("192.168.1.500" =~ Resolv::IPv4::Regex) #=> false

!!("ff02::1"    =~ Resolv::IPv6::Regex) #=> true
!!("ff02::1::1" =~ Resolv::IPv6::Regex) #=> false

玩得开心!

更新(2018-10-08):

从下面的 cmets 中,我喜欢非常短的版本:

!!(ip_string =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]))

非常优雅的导轨(也是下面的答案):

validates :ip,
          :format => {
            :with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
          }

【讨论】:

  • 只是为了简化事情,((ip_string =~ Resolv::IPv4::Regex) || (ip_string =~ Resolv::IPv6::Regex)) ? true : false
  • 进一步简化!!((ip_string =~ Resolv::IPv4::Regex) || (ip_string =~ Resolv::IPv6::Regex))
  • 我更喜欢!!(ip_string =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]))
  • 非常有帮助的答案。
【解决方案2】:

为什么不让a library 为您验证呢?不应引入无法维护的复杂正则表达式。

% gem install ipaddress

然后,在您的应用程序中

require "ipaddress"

IPAddress.valid? "192.128.0.12"
#=> true

IPAddress.valid? "192.128.0.260"
#=> false

# Validate IPv6 addresses without additional work.
IPAddress.valid? "ff02::1"
#=> true

IPAddress.valid? "ff02::ff::1"
#=> false


IPAddress.valid_ipv4? "192.128.0.12"
#=> true

IPAddress.valid_ipv6? "192.128.0.12"
#=> false

您也可以使用 Ruby 的内置 IPAddr 类,但它不适合验证。

当然,如果 IP 地址是由应用程序服务器或框架提供给您的,则根本没有理由进行验证。只需使用提供给您的信息,并优雅地处理任何异常。

【讨论】:

    【解决方案3】:

    我使用的这个正则表达式是我找到的here

    /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

    【讨论】:

      【解决方案4】:

      试试这个

      使用IPAddr

      require 'ipaddr'
      true if IPAddr.new(ip) rescue false
      

      【讨论】:

        【解决方案5】:

        由于大多数答案都没有谈到 IPV6 验证,我遇到了类似的问题。 正如@wingfire 提到的那样,我使用 Ruby 正则表达式库解决了这个问题。

        但我也使用 Regexp 库来使用它的 union 方法,如 here 解释的那样

        我有这个验证码:

        validates :ip, :format => { 
                          :with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
                        }
        

        希望这可以帮助某人!

        【讨论】:

          【解决方案6】:
          require 'ipaddr'
          
          def is_ip?(ip)
            !!IPAddr.new(ip) rescue false
          end
          
          is_ip?("192.168.0.1")
          => true
          
          is_ip?("www.google.com")
          => false
          

          或者,如果您不介意扩展核心类:

          require 'ipaddr'
          
          class String
            def is_ip?
              !!IPAddr.new(self) rescue false
            end
          end
          
          "192.168.0.1".is_ip?
          => true
          
          "192.168.0.512".is_ip?
          => false
          

          【讨论】:

            【解决方案7】:

            使用正则表达式匹配有效的 IP 地址

            ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$
            

            而不是

            ^([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}$
            

            因为许多正则表达式引擎匹配 OR 序列中的第一种可能性

            你可以试试你的正则表达式引擎:10.48.0.200

            测试差异here

            【讨论】:

              【解决方案8】:

              使用http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html 它会为您执行验证。只要用 false 挽救异常,你就知道它是无效的。

              1.9.3p194 :002 > IPAddr.new('1.2.3.4')
               => #<IPAddr: IPv4:1.2.3.4/255.255.255.255> 
              1.9.3p194 :003 > IPAddr.new('1.2.3.a')
              ArgumentError: invalid address
                from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in initialize'
                from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/ipaddr.rb:493:in `initialize'
                from (irb):3:in `new'
                from (irb):3
                from /usr/local/rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
              

              【讨论】:

                【解决方案9】:
                require 'ipaddr'
                !(IPAddr.new(str) rescue nil).nil?
                

                我用它来快速检查,因为它使用内置库。同时支持 ipv4 和 ipv6。虽然它不是很严格,例如它说'999.999.999.999'是有效的。如果您需要更高的精度,请查看获胜答案。

                【讨论】:

                • !!IPAddr.new(str) rescue false 会是更好的代码
                • 赞成至少当前库 (Ruby 2.4.2) 仅当所有数字组都在允许范围内(IPv4 为 0 到 255)时才能正确验证地址。 IPAddr.new '999.999.999.999' => IPAddr::InvalidAddressError: invalid address
                【解决方案10】:

                以上所有答案都假设 IPv4...您必须问问自己,在网络迁移到 IPv6 的这一天添加这些检查,将您的应用程序限制为 IPv4 是多么明智。

                如果你问我:根本不要验证它。相反,只需将字符串按原样传递给将使用 IP 地址的网络组件并让它们进行验证。捕获错误时他们将抛出的异常,并使用该信息告诉用户发生了什么。不要重新发明轮子,以他人的工作为基础。

                【讨论】:

                • 顺便说一句,你在request.env['REMOTE_ADDR'] 中得到的总是一个有效的IP 地址,除非网络服务器把它弄乱了!无需检查
                • 这是最好的建议。程序员沉迷于语法验证,但不应该:将其传递给将要使用它的程序……并验证它。
                【解决方案11】:

                使用正则表达式验证:

                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
                

                【讨论】:

                【解决方案12】:

                字符串形式的 IP 地址必须正好包含四个数字,用点分隔。每个数字必须在 0 到 255 之间,包括 0 到 255。

                【讨论】:

                • 还请记住,您必须检查本地网络 ip 和其他保留的 ip 地址,例如 192.168.x.x 和 127.0.0.1
                • 为什么?你实际上可以从你自己的网络访问你自己的网站:)(甚至在本地主机上使用 lynx)。
                猜你喜欢
                • 2014-07-25
                • 2014-05-02
                • 2011-03-28
                • 2012-11-28
                • 1970-01-01
                • 1970-01-01
                • 2012-04-14
                • 2014-02-20
                相关资源
                最近更新 更多