偶边学边做的一个限制IP地址的ASP函数,请提意见!

tsxnb 2009-07-29 04:01:18
偶边学边做的一个限制IP地址的ASP函数,请提意见!

用ASP编写一个信息管理系统,要求后台登录的管理用户与固定IP绑定,前台部份网页只允许特定部门(范围IP)的用户浏览。
于是编写了一个限制IP地址的ASP函数,能同时支持如下格式的IP地址范围:

*宽范围,例如:10.11*.*.*,10.22.33.*
-之间,例如:10.111.222.0-31,10.111.200-230.0
~区间,例如:10.111.222.222~10.222.111.111
/子网掩码,例如:10.111.222.0/255.255.255.0,10.111.222.40/255.255.255.224
/CIDR,例如:10.111.222.0/23,10.111.222.40/27


<%
'************************************************************
'Function CheckIp(cInput_Ip,cBound_Ip)
'功能:单一字段就能限制范围IP的ASP函数。参考qqdao@263.net由tsxnb(392324126@qq.com)于2009-06-23改进,“*”或“-”可以出现在任何位置,支持区间“~”和子网掩码“/”及CIDR等表达式,兼容旧版本。
'参数:cInput_Ip,待检查的ip,也就是Request.ServerVariables("REMOTE_ADDR")
' cBound_Ip,是给定的范围,可以存到库里,格式为单个ip和范围ip,范围ip使用“*”或“-”,以及“~”和“/”表示,多个范围用逗号“,”隔开。
' 例如 10.11*.*.*:允许,10.115.227-229.0:拒绝指定部门登录,10.115.228.0-31:允许登录,10.115.228.8:拒绝,10.22.33.44/25:拒绝,10.22.33.44/255.255.255.248:允许
'返回值: true/false 即允许或拒绝登录
'说明:给定的范围为空则全部允许,未指明允许或拒绝则全部拒绝,首先根据逗号,循环,然后处理宽范围* 再判断是否含有"-",如果有则进行拆分处理,之后处理~和/。
'************************************************************
' 代码调用演示:
if CheckIp( "10.111.222.9", "10.11*.*.*:允许登录,,10.111.200- 230.0::拒绝,10.111.222.0-31:允许,10.111.222.7~10.111.222.27:允许 " ) then '星号*最多4个,任意位置可有范围-
response.write "登录成功"
else
response.write "您的ip不被允许"
end if
'************************************************************
function CheckIp(cInput_Ip,cBound_Ip)
dim cSingle_Ip,cTemp_IP,cStart_IP,cEnd_Ip , cSingle_Ip4
CheckIp = false '默认拒绝

cBound_Ip= Replace(cBound_Ip," ","") '去除半角空格,防止*的左边包含空格,影响对比。
cBound_Ip= Replace(cBound_Ip," ","") '去除全角空格
cBound_Ip= Replace(cBound_Ip,",",",") '改逗号,为,
cBound_Ip= Replace(cBound_Ip,":",":") '改冒号:为:
cBound_Ip= Replace(cBound_Ip,"-","-") '改减号-为-
cBound_Ip= Replace(cBound_Ip,"*","*") '改星号*为*
cBound_Ip= Replace(cBound_Ip,"~","~") '改~为~
cBound_Ip= Replace(cBound_Ip,"/","/") '改/为/
cBound_Ip= Replace(cBound_Ip,"<br>",",") '处理换行符
cBound_Ip= Replace(cBound_Ip,"<br />",",")
cBound_Ip= Replace(cBound_Ip,chr(10),",")
cBound_Ip= Replace(cBound_Ip,chr(13),",")
cBound_Ip= Replace(cBound_Ip,vbCrLf,",")
cBound_Ip= Replace(cBound_Ip,"ALLOW","允许") '改字符ALLOW为允许,以便兼容旧版本。
cBound_Ip= Replace(cBound_Ip,"REFUSE","拒绝") '改字符REFUSE为拒绝,以便兼容旧版本。
cBound_Ip= Replace(cBound_Ip,";",",") '改分号;为逗号,显示更加清晰,同时便兼容旧版本。

if cBound_Ip="" or isnull(cBound_Ip) then '给定的范围为空则全部允许
CheckIp = true
exit function
end if
if Instr(cBound_Ip,"拒绝")=0 and Instr(cBound_Ip,"允许")=0 then '未指明允许或拒绝则全部拒绝。
CheckIp = false
exit function
end if

cSingle_Ip=split(cBound_Ip,",") '以逗号,循环,如果两个逗号之间无内容则下一循环。
for i=0 to ubound(cSingle_Ip)
if Instr(cSingle_Ip(i),"拒绝") <> 0 then '就是拒绝了
cTemp_IP = left(cSingle_Ip(i),instr(cSingle_Ip(i),":")-1) '连续出现多个冒号时只与最左边的冒号有关。

if Instr(cTemp_IP,"*") <> 0 then '是宽范围
cStart_IP = left(cTemp_IP,instr(cTemp_IP,"*")-1)
if left(cInput_Ip,len(cStart_IP))=cStart_IP then '任意位置的首个*号左边相同都拒绝。
CheckIp = false
'exit function '即使拒绝也不结束,仍受之后的规定而改变。
end if
end if

if Instr(cTemp_IP,"-") = 0 then '范围-的处理
cStart_IP = cTemp_IP
cEnd_Ip = cTemp_IP
else
cSingle_Ip4=split(cTemp_IP,".") '共4节
if Instr(cSingle_Ip4(3),"-") <> 0 then '第4节有-
'以下两行是原来的代码,在四节都有-时例如10-20.118-120.184-188.0-9会出错。
'cStart_IP = left(cTemp_IP,instr(cTemp_IP,"-")-1)
'cEnd_Ip = left(cStart_IP,InStrRev(cStart_IP,".")-1)+"."+mid(cTemp_IP,instr(cTemp_IP,"-")+1) '注解:最后点之前的内容,补点,以及-之后的数值
cStart_IP = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+cSingle_Ip4(2)+"."+ left(cSingle_Ip4(3),instr(cSingle_Ip4(3),"-")-1)
cEnd_Ip = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+cSingle_Ip4(2)+"."+ mid(cSingle_Ip4(3),instr(cSingle_Ip4(3),"-")+1)
end if
if Instr(cSingle_Ip4(2),"-") <> 0 then '第3节有-
cStart_IP = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+ left(cSingle_Ip4(2),instr(cSingle_Ip4(2),"-")-1) +".0"
cEnd_Ip = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+ mid(cSingle_Ip4(2),instr(cSingle_Ip4(2),"-")+1) +".255"
end if
if Instr(cSingle_Ip4(1),"-") <> 0 then '第2节有-
cStart_IP = cSingle_Ip4(0)+"."+ left(cSingle_Ip4(1),instr(cSingle_Ip4(1),"-")-1) +".0.0"
cEnd_Ip = cSingle_Ip4(0)+"."+ mid(cSingle_Ip4(1),instr(cSingle_Ip4(1),"-")+1) +".255.255"
end if
if Instr(cSingle_Ip4(0),"-") <> 0 then '第1节有-
cStart_IP = left(cSingle_Ip4(0),instr(cSingle_Ip4(0),"-")-1) +".0.0.0"
cEnd_Ip = mid(cSingle_Ip4(0),instr(cSingle_Ip4(0),"-")+1) +".255.255.255"
end if
end if

if Instr(cTemp_IP,"~") <> 0 then '区间~的处理
cStart_IP = left(cTemp_IP,instr(cTemp_IP ,"~")-1)
cEnd_Ip = mid(cTemp_IP,instr(cTemp_IP,"~")+1)
end if

if Instr(cTemp_IP,"/") <> 0 then '/子网掩码和CIDR的处理
'编写中
end if

if Ip2Str(cInput_Ip)>=Ip2Str(cStart_IP) and Ip2Str(cInput_Ip)<=Ip2Str(cEnd_Ip) then
CheckIp = false
'exit function '即使拒绝也不结束,仍受之后的规定而改变。
end if


elseif Instr(cSingle_Ip(i),"允许") <> 0 then '就是允许了
cTemp_IP = left(cSingle_Ip(i),instr(cSingle_Ip(i),":")-1)

if Instr(cTemp_IP,"*") <> 0 then '是宽范围
cStart_IP = left(cTemp_IP,instr(cTemp_IP,"*")-1)
if left(cInput_Ip,len(cStart_IP))=cStart_IP then
CheckIp = true
' exit function '即使允许也不结束,仍受之后的规定而改变。
end if
end if

if Instr(cTemp_IP,"-") = 0 then '范围-的处理
cStart_IP = cTemp_IP
cEnd_Ip = cTemp_IP
else
cSingle_Ip4=split(cTemp_IP,".") '共4节
if Instr(cSingle_Ip4(3),"-") <> 0 then '第4节有-
cStart_IP = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+cSingle_Ip4(2)+"."+ left(cSingle_Ip4(3),instr(cSingle_Ip4(3),"-")-1)
cEnd_Ip = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+cSingle_Ip4(2)+"."+ mid(cSingle_Ip4(3),instr(cSingle_Ip4(3),"-")+1)
end if
if Instr(cSingle_Ip4(2),"-") <> 0 then '第3节有-
cStart_IP = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+ left(cSingle_Ip4(2),instr(cSingle_Ip4(2),"-")-1) +".0"
cEnd_Ip = cSingle_Ip4(0)+"."+cSingle_Ip4(1)+"."+ mid(cSingle_Ip4(2),instr(cSingle_Ip4(2),"-")+1) +".255"
end if
if Instr(cSingle_Ip4(1),"-") <> 0 then '第2节有-
cStart_IP = cSingle_Ip4(0)+"."+ left(cSingle_Ip4(1),instr(cSingle_Ip4(1),"-")-1) +".0.0"
cEnd_Ip = cSingle_Ip4(0)+"."+ mid(cSingle_Ip4(1),instr(cSingle_Ip4(1),"-")+1) +".255.255"
end if
if Instr(cSingle_Ip4(0),"-") <> 0 then '第1节有-
cStart_IP = left(cSingle_Ip4(0),instr(cSingle_Ip4(0),"-")-1) +".0.0.0"
cEnd_Ip = mid(cSingle_Ip4(0),instr(cSingle_Ip4(0),"-")+1) +".255.255.255"
end if
end if

if Instr(cTemp_IP,"~") <> 0 then '区间~的处理
cStart_IP = left(cTemp_IP,instr(cTemp_IP ,"~")-1)
cEnd_Ip = mid(cTemp_IP,instr(cTemp_IP,"~")+1)
end if

if Instr(cTemp_IP,"/") <> 0 then '/子网掩码和CIDR的处理
'编写中
end if

if Ip2Str(cInput_Ip)>=Ip2Str(cStart_IP) and Ip2Str(cInput_Ip)<=Ip2Str(cEnd_Ip) then
CheckIp =true
else
'CheckIp =false '应当删除这一行,使得*在允许中生效。
end if
end if
next
end function

'******************************
'Function Ip2Str(cIp)
'Created by qqdao, qqdao@263.net 2001/11/28
'参考动网ip算法
'参数:cIp ip地址
'返回值: 转换后数值
'******************************
function Ip2Str(cIp)
Dim str1,str2,str3,str4
Dim cIp_Temp
if cIp="127.0.0.1" then cIp="192.168.0.1"
str1=left(cIp,instr(cIp,".")-1)
cIp_Temp=mid(cIp,instr(cIp,".")+1)
str2=left(cIp_Temp,instr(cIp_Temp,".")-1)
cIp_Temp=mid(cIp_Temp,instr(cIp_Temp,".")+1)
str3=left(cIp_Temp,instr(cIp_Temp,".")-1)
str4=mid(cIp_Temp,instr(cIp_Temp,".")+1)
if isNumeric(str1)=0 or isNumeric(str2)=0 or isNumeric(str3)=0 or isNumeric(str4)=0 then
'
else
Ip2Str=cint(str1)*256*256*256+cint(str2)*256*256+cint(str3)*256+cint(str4) '不应当再减1
end if
'response.write "测试cIP:"& cip & "转换成十进制:" & Ip2Str & "<BR>"
end function
%>
...全文
156 点赞 收藏 8
写回复
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
qqmnme 2011-05-26
学习了,不过看不懂啊
回复
yy2004005 2009-08-12
学习,学习,我正好也遇到这个情况,希望能够与楼主交流!!可否留下联系方式
回复
tsxnb 2009-07-30
[Quote=引用 5 楼 tsxnb 的回复:]
要计算10.11.22.33/21 网段的开始地址、结束地址(或称 子网地址、广播地址),

有无简便的计算公式?
[/Quote]

自问自答:

借用路由器设置中的通配符掩码(ildcard-mask,又称反向子网掩码,反掩码),问题解决!
例如子网掩码255.255.248.0的通配符掩码是0.0.7.255 (由255.255.255.255-255.255.248.0所得)

1、把IP地址、子网掩码、CIDR、通配符掩码 都转换成十进制数值。

2、网段的开始地址(子网地址)=主机地址 AND 子网掩码
例如(10.11.22.33) and (255.255.248.0)=168498721 and 4294965248=168497152即10.11.16.0

3、网段的结束地址(广播地址)=网段的开始地址(子网地址) + 通配符掩码
例如(10.11.16.0) + (255.255.255.255-255.255.248.0) = 168497152 + 2047=168499199即10.11.23.255

因此,10.11.22.33/21 网段的范围是10.11.16.0 ~ 10.11.23.255
回复
tsxnb 2009-07-30
要计算10.11.22.33/21 网段的开始地址、结束地址(或称 子网地址、广播地址),

有无简便的计算公式?
回复
tsxnb 2009-07-29
楼上的代码很简练,但我不知道第三个参数RP (正则对象) 怎么书写,能不能提供只测1个限制IP的完整演示?
只支持*,没有其他范围的格式,IP限制库可能很大。
回复
jnwentao 2009-07-29
太复杂了,看看我写的这个

传入三个参数
userip:待检查的参数
iparr:一个用换行分隔的IP限制库
rp:regExp一个正则对象
函数返回一个Boolean对象,返回true时表示 IP在限制范围内,可以用*号

function checkip(userip,iparr,rp)
checkip=false
Dim ip
iparr = replace(iparr,".","\.") '将ip分隔符注释
iparr = replace(iparr,"*","\d+") '将*号标示为数字表达式
iparr=split(iparr,vbcrlf) '生成数组
rp.ignorecase = true
rp.global = false
for each ip in iparr
rp.pattern = ip
if rp.test(userip) then
checkip = true
exit for
End if
next
End function
回复
tsxnb 2009-07-29
对子网掩码的处理,发现了个简便的换算方法,例如:

子网掩码/255.255.255.128换算成十进制是255*256*256*256+255*256*256+255*256+128=4294967168
相应的CIDR /25换算成十进制是2^32-2^(32-25)=4294967168

子网掩码换算表:
CIDR名称 换算公式 十进制 子网掩码
/32 2^32-2^(32-32) 4294967295 255.255.255.255
/31 2^32-2^(32-31) 4294967294 255.255.255.254
/30 2^32-2^(32-30) 4294967292 255.255.255.252
/29 2^32-2^(32-29) 4294967288 255.255.255.248
/28 2^32-2^(32-28) 4294967280 255.255.255.240
/27 2^32-2^(32-27) 4294967264 255.255.255.224
/26 2^32-2^(32-26) 4294967232 255.255.255.192
/25 2^32-2^(32-25) 4294967168 255.255.255.128
/24 2^32-2^(32-24) 4294967040 255.255.255.0
/23 2^32-2^(32-23) 4294966784 255.255.254.0
/22 2^32-2^(32-22) 4294966272 255.255.252.0
/21 2^32-2^(32-21) 4294965248 255.255.248.0
/20 2^32-2^(32-20) 4294963200 255.255.240.0
/19 2^32-2^(32-19) 4294959104 255.255.224.0
/18 2^32-2^(32-18) 4294950912 255.255.192.0
/17 2^32-2^(32-17) 4294934528 255.255.128.0
/16 2^32-2^(32-16) 4294901760 255.255.0.0
/15 2^32-2^(32-15) 4294836224 255.254.0.0
/14 2^32-2^(32-14) 4294705152 255.252.0.0
/13 2^32-2^(32-13) 4294443008 255.248.0.0
/12 2^32-2^(32-12) 4293918720 255.240.0.0
/11 2^32-2^(32-11) 4292870144 255.224.0.0
/10 2^32-2^(32-10) 4290772992 255.192.0.0
/9 2^32-2^(32-9) 4286578688 255.128.0.0
/8 2^32-2^(32-8) 4278190080 255.0.0.0
/7 2^32-2^(32-7) 4261412864 254.0.0.0
/6 2^32-2^(32-6) 4227858432 252.0.0.0
/5 2^32-2^(32-5) 4160749568 248.0.0.0
/4 2^32-2^(32-4) 4026531840 240.0.0.0
/3 2^32-2^(32-3) 3758096384 224.0.0.0
/2 2^32-2^(32-2) 3221225472 192.0.0.0
/1 2^32-2^(32-1) 2147483648 128.0.0.0
/0 2^32-2^(32-0) 0 0.0.0.0

回复
chenlongit 2009-07-29
JF 先
回复
发动态
发帖子
ASP
创建于2007-09-28

2.8w+

社区成员

ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境。
申请成为版主
社区公告
暂无公告