29


10

文字列の値がIPアドレスであるかどうかを確認する方法

私がこれをするとき

ip = request.env["REMOTE_ADDR"]

クライアントのIPアドレスを取得します。 しかし、変数の値が実際にIPであるかどうかを検証したい場合はどうでしょうか? それ、どうやったら出来るの?

助けてください。 前もって感謝します。 この質問が繰り返される場合は申し訳ありませんが、私はそれを見つける努力をしませんでした…​

編集

IPv6 IPはどうですか??

12 Answer


33


http://github.com/bluemonk/ipaddress [ライブラリ]で検証してみませんか? 維持が不可能な複雑な正規表現を導入しないでください。

% 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アドレスが提供される場合、検証する理由はまったくありません。 与えられた情報を使用し、例外を適切に処理するだけです。


30


Rubyには、標準ライブラリに必要な正規表現が既に含まれています。 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):

以下のコメントから、私は非常に短いバージョンが大好きです。

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

レールで非常にエレガント(以下からの回答):

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


14


require 'ipaddr'
!(IPAddr.new(str) rescue nil).nil?

組み込みのライブラリを使用するため、クイックチェックに使用します。 ipv4とipv6の両方をサポートします。 それほど厳密ではありませんが、たとえば「999.999.999.999」が有効であると表示されます。 さらに精度が必要な場合は、勝利の答えをご覧ください。


8


回答のほとんどはIPV6検証について述べていないため、同様の問題がありました。 @wingfireが言及したように、Ruby Regexライブラリを使用して解決しました。

しかし、http://apidock.com/ruby/v1_9_3_392/Regexp/union/class [こちら]で説明されているように、Regexpライブラリを使用して「union」メソッドを使用しました

私は検証のためにこのコードを持っています:

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

これが誰かを助けることを願っています!


4


上記のすべての回答はIPv4を想定しています…​ ネットがIPv6に移行する今日、この種のチェックを追加して、アプリをIPv4に制限するのが賢明かどうかを自問する必要があります。

あなたが私に尋ねた場合:それをまったく検証しないでください。 代わりに、IPアドレスを使用するネットワークコンポーネントに文字列をそのまま渡し、検証を行わせます。 間違っているときにスローする例外をキャッチし、その情報を使用して何が起こったかをユーザーに伝えます。 車輪を再発明するのではなく、他の人の仕事の上に構築してください。


4


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')
 => #
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 `'


3


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


2


これを試して

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


1


私が使用したこの正規表現https://www.regular-expressions.info/ip.html[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]?)$ / `


0


文字列形式のIPアドレスには、ドットで区切られた正確に4つの数字が含まれている必要があります。 各数値は、0〜255の範囲内である必要があります。