可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
when I do this
ip = request.env["REMOTE_ADDR"]
I get the client's IP address it it. But what if I want to validate whether the value in the variable is really an IP?
How do I do that?
Please help.
Thanks in advance. And sorry if this question is repeated, I didn't take the effort of finding it...
EDIT
What about IPv6 IP's??
回答1:
Why not let a library validate it for you? You shouldn't introduce complex regular expressions that are impossible to maintain.
% gem install ipaddress
Then, in your application
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
You can also use Ruby's built-in IPAddr
class, but it doesn't lend itself very well for validation.
Of course, if the IP address is supplied to you by the application server or framework, there is no reason to validate at all. Simply use the information that is given to you, and handle any exceptions gracefully.
回答2:
Ruby has already the needed Regex in the standard library.
Checkout 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
If you like it the short way ...
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
Have fun!
Update (2018-10-08):
From the comments below i love the very short version:
!!(ip_string =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]))
Very elegant with rails (also an answer from below):
validates :ip,
:format => {
:with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
}
回答3:
require 'ipaddr'
!(IPAddr.new(str) rescue nil).nil?
I use it for quick check because it uses built in library. Supports both ipv4 and ipv6. It is not very strict though, it says '999.999.999.999' is valid, for example. See the winning answer if you need more precision.
回答4:
As most of the answers don't speak about IPV6 validation, I had the similar problem.
I solved it by using the Ruby Regex Library, as @wingfire mentionned it.
But I also used the Regexp Library to use it's union
method as explained here
I so have this code for a validation :
validates :ip, :format => {
:with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
}
Hope this can help someone !
回答5:
All answers above asume IPv4... you must ask yourself how wise it is to limit you app to IPv4 by adding these kind of checks in this day of the net migrating to IPv6.
If you ask me: Don't validate it at all. Instead just pass the string as-is to the network components that will be using the IP address and let them do the validation. Catch the exceptions they will throw when it is wrong and use that information to tell the user what happened. Don't re-invent the wheel, build upon the work of others.
回答6:
Use http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html it performs validation for you. Just rescue the exception with false and you know that it was invalid.
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>'
回答7:
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
Or, if you don't mind extending core classes:
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
回答8:
Try this
Use IPAddr
require 'ipaddr'
true if IPAddr.new(ip) rescue false
回答9:
This regular expression I use which I found 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]?)$/
回答10:
IP address in a string form must contain exactly four numbers, separated by dots. Each number must be in a range between 0 and 255, inclusive.
回答11:
Validate using regular expression:
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
回答12:
for match a valid IP adress with regexp use
^(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}$
instead of
^([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}$
because many regex engine match the first possibility in the OR sequence
you can try your regex engine : 10.48.0.200
test the difference here