news 2026/9/16 4:21:05

ASP老系统IP白名单硬隔离实现与VBScript网段校验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ASP老系统IP白名单硬隔离实现与VBScript网段校验

简介:这是一套基于经典ASP技术开发的公安行业网站管理系统实战案例,面向Web开发初学者及政务系统维护人员,聚焦IP白名单访问控制这一典型安全需求,帮助理解传统IIS+ASP架构下的权限管控实现逻辑。资源包共1195个文件,主体为298个ASP核心业务脚本(含manage_web.asp、zhiban.asp等管理模块)、467个GIF/JPG/PNG图形资源、69个JS交互脚本与51个HTML前端页面,辅以CSS样式、PSD设计源稿及INI配置文件,完整呈现了从登录鉴权、值班管理到内容发布的功能链路,压缩包体积25.05MB。已有79人学习下载,可直接部署调试,深入掌握Request.ServerVariables('REMOTE_ADDR')获取客户端IP、服务端条件跳转、ASP内置对象(Session/Server/Response)协同使用等关键技能,并通过nzcms系列ASP文件结构理解国产化CMS早期演进路径。

1. 这不是普通ASP网站,而是一套带IP白名单硬隔离的公安内网管理前端

宁志公安局网站管理系统 IP限制签收版 v2022.4.30.zip 看似是常规ASP站点压缩包,实则在架构层就做了强边界控制——它不依赖IIS权限配置或防火墙策略,而是把IP校验逻辑直接嵌入到每个核心页面(manage_web.aspzhiban.asplist.asp)的顶部执行流中。这意味着:即使攻击者绕过登录页、伪造Session、甚至拿到管理员Cookie,只要IP不在白名单内,连index.asp的HTML骨架都吐不出来。这种“请求即拦截”的设计,比单纯在登录环节做IP判断更彻底。它面向的是公安系统内部网络环境:IP段固定(如10.128.0.0/16)、终端可控、无公网暴露面,因此不追求OAuth或JWT等现代鉴权模型,而是用最轻量、最确定的Request.ServerVariables("REMOTE_ADDR")做第一道闸机。如果你正在维护一个局域网内的政务类ASP老系统,且需要快速落地可审计的访问控制,这个版本的实现思路比重写整套后端更务实。

2. IP限制机制的三层嵌套实现与VBScript硬编码逻辑解析

2.1 白名单存储结构:从data.asax到内存缓存的加载链路

该系统未使用数据库存储IP白名单,而是将规则固化在data.asax文件中——这是ASP时代典型的配置即代码实践。打开data.asax可见如下结构:

<!-- data.asax --> <% ' 公安局内网白名单(IPv4) Dim g_IPList g_IPList = Array( _ "10.128.1.5", _ "10.128.1.12", _ "10.128.2.33", _ "10.128.2.201", _ "10.128.3.0/24", _ ' 支持CIDR网段 "10.128.4.0/24" _ ) %>

提示:data.asax在ASP中属于Application级全局文件,IIS启动时自动加载一次,所有会话共享g_IPList数组。这种设计避免了每次请求都读取文件或查库,但修改后需重启IIS或等待Application超时回收。

关键点在于10.128.3.0/24这类CIDR写法——系统并未调用第三方组件,而是用纯VBScript实现网段匹配。其核心函数位于nzcms_dna.asp中:

' nzcms_dna.asp 中的 IPInSubnet 函数 Function IPInSubnet(ip, subnet) Dim ipParts, netParts, maskBits, i If InStr(subnet, "/") = 0 Then IPInSubnet = (ip = subnet) : Exit Function End If ipParts = Split(ip, ".") netParts = Split(Split(subnet, "/")(0), ".") maskBits = CInt(Split(subnet, "/")(1)) ' 将IP和网段转为32位整数 Dim ipNum, netNum ipNum = CLng(ipParts(0)) * 2^24 + CLng(ipParts(1)) * 2^16 + CLng(ipParts(2)) * 2^8 + CLng(ipParts(3)) netNum = CLng(netParts(0)) * 2^24 + CLng(netParts(1)) * 2^16 + CLng(netParts(2)) * 2^8 + CLng(netParts(3)) ' 计算子网掩码 Dim mask mask = (2^maskBits - 1) * 2^(32 - maskBits) IPInSubnet = ((ipNum And mask) = (netNum And mask)) End Function

这段代码逻辑清晰:先将IP和网段地址转为32位整数,再通过位运算(And)比对是否落在同一子网。它规避了正则表达式或字符串分割的性能损耗,在IIS 5.1+环境下毫秒级完成判断。注意maskBits必须是整数,若传入/25以外的值(如/33)会导致2^33溢出,此时函数返回False——这反而是安全兜底行为。

2.2 全局拦截入口:nzcms_2.asp中的强制校验链

所有业务页面(manage_web.asp,zhiban.asp等)顶部均包含:

<!--#include file="nzcms_2.asp"-->

nzcms_2.asp的核心逻辑是:

' nzcms_2.asp Dim clientIP, isAllowed, i clientIP = Request.ServerVariables("REMOTE_ADDR") ' 处理代理转发场景(X-Forwarded-For) If Request.ServerVariables("HTTP_X_FORWARDED_FOR") <> "" Then clientIP = Split(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ",")(0) End If isAllowed = False For i = 0 To UBound(g_IPList) If InStr(g_IPList(i), "/") > 0 Then If IPInSubnet(clientIP, g_IPList(i)) Then isAllowed = True : Exit For End If Else If clientIP = g_IPList(i) Then isAllowed = True : Exit For End If End If Next If Not isAllowed Then Response.Status = "403 Forbidden" Response.Write "<h1>访问被拒绝</h1><p>您的IP地址 " & clientIP & " 不在授权列表中。</p>" Response.End End If

注意:HTTP_X_FORWARDED_FOR的处理仅取第一个IP,防止客户端伪造长链。Response.End是关键——它立即终止响应流,后续ASP代码(包括数据库连接、HTML渲染)完全不执行。这比跳转到错误页更安全,杜绝了任何信息泄露可能。

2.3 动态IP适配:zhiban.asp中的值班员临时放行机制

zhiban.asp作为值班管理页面,实现了特殊放行逻辑:当值班员使用工号+密码登录后,其当前IP会被临时加入Application("tempIPList")集合(有效期2小时)。该机制在zhiban.asp中体现为:

' zhiban.asp 登录成功后追加 If loginSuccess Then Dim tempIPs If IsEmpty(Application("tempIPList")) Then tempIPs = Array(clientIP) Else tempIPs = Application("tempIPList") ReDim Preserve tempIPs(UBound(tempIPs) + 1) tempIPs(UBound(tempIPs)) = clientIP End If Application.Lock Application("tempIPList") = tempIPs Application("tempIPExpire") = DateAdd("h", 2, Now()) Application.UnLock End If

nzcms_2.asp的校验逻辑随后扩展为:

' 在原有 isAllowed 判断前插入 If Not IsEmpty(Application("tempIPList")) Then If Application("tempIPExpire") > Now() Then For i = 0 To UBound(Application("tempIPList")) If clientIP = Application("tempIPList")(i) Then isAllowed = True : Exit For End If Next Else Application.Lock Application("tempIPList") = Empty Application("tempIPExpire") = Empty Application.UnLock End If End If

这种“静态白名单+动态临时授权”双轨制,既保障了日常访问的确定性,又满足了值班场景的灵活性。Application对象的锁机制(Lock/UnLock)确保了多用户并发写入的安全性。

3. 关键页面功能拆解与<% %>嵌入式开发模式实战

3.1manage_web.asp:基于ADO的SQL Server数据操作模板

manage_web.asp是后台管理主入口,其数据库操作严格遵循ASP经典模式:ConnectionRecordsetClose。以用户列表查询为例:

<!-- manage_web.asp 片段 --> <% Dim conn, rs, sql Set conn = Server.CreateObject("ADODB.Connection") conn.Open "Provider=SQLOLEDB;Data Source=10.128.1.10;Initial Catalog=nzcms_db;User ID=sa;Password=Admin@2022;" sql = "SELECT id, username, dept, last_login FROM users WHERE status=1 ORDER BY last_login DESC" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open sql, conn, 1, 3 ' adOpenKeyset, adLockOptimistic If Not rs.EOF Then %> <table border="1"> <tr><th>ID</th><th>用户名</th><th>部门</th><th>最后登录</th></tr> <% Do While Not rs.EOF %> <tr> <td><%= rs("id") %></td> <td><%= Server.HTMLEncode(rs("username")) %></td> <td><%= rs("dept") %></td> <td><%= FormatDateTime(rs("last_login"), 2) %></td> </tr> <% rs.MoveNext Loop %> </table> <% Else Response.Write "<p>暂无活跃用户</p>" End If rs.Close Set rs = Nothing conn.Close Set conn = Nothing %>

提示:Server.HTMLEncode()是必备防护,防止XSS;FormatDateTime(rs("last_login"), 2)中参数2对应vbLongDate,输出如2022年4月30日,符合国内政务系统日期习惯。连接字符串明文写死在代码中,虽不符合现代安全规范,但在内网隔离环境中属常见做法。

3.2list.asp:分页与<%=短标记的高效渲染

list.asp负责案件列表展示,采用客户端分页(因数据量小),但<%=短标记的使用极大提升了HTML生成效率:

<!-- list.asp --> <% Dim pageSize, pageNum, totalRecords, totalPages pageSize = 15 pageNum = CInt(Request.QueryString("page")) If pageNum < 1 Then pageNum = 1 ' 获取总记录数(单次查询) Set rs = Server.CreateObject("ADODB.Recordset") rs.Open "SELECT COUNT(*) FROM cases WHERE status IN (1,2)", conn, 1, 1 totalRecords = rs(0) rs.Close totalPages = Int((totalRecords - 1) / pageSize) + 1 If pageNum > totalPages Then pageNum = totalPages ' 获取当前页数据 sql = "SELECT TOP " & pageSize & " * FROM cases WHERE id NOT IN " & _ "(SELECT TOP " & ((pageNum-1)*pageSize) & " id FROM cases ORDER BY create_time DESC) " & _ "ORDER BY create_time DESC" rs.Open sql, conn, 1, 1 %> <div class="case-list"> <% Do While Not rs.EOF %> <div class="case-item"> <h3><%= Server.HTMLEncode(rs("title")) %></h3> <p><strong>编号:</strong><%= rs("case_no") %> | <strong>状态:</strong><%= IIf(rs("status")=1,"待处理","已归档") %> | <strong>时间:</strong><%= FormatDateTime(rs("create_time"), 2) %></p> </div> <% rs.MoveNext : Loop %> </div> <!-- 分页导航 --> <div class="pagination"> <% For i = 1 To totalPages %> <a href="?page=<%= i %>" class="<%= IIf(i=pageNum,"active","") %>"><%= i %></a> <% Next %> </div>

<%=<% Response.Write的简写,减少字符输入,提升可读性。IIf()函数用于三元表达式,IIf(rs("status")=1,"待处理","已归档")比写完整If...Else更紧凑。分页SQL采用NOT IN子查询,虽在大数据量下有性能瓶颈,但对公安系统日均百条案件的场景足够高效。

3.3nzcms_bq.asp:BBS模块中的防注入参数化查询实践

nzcms_bq.asp是内部论坛模块,其发帖功能展示了ASP时代较先进的防注入手段——参数化查询(通过Command对象):

' nzcms_bq.asp 发帖处理 If Request.Form("action") = "post" Then Dim cmd Set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "INSERT INTO posts (title, content, author_id, create_time) VALUES (?, ?, ?, GETDATE())" cmd.Parameters.Append cmd.CreateParameter("@title", 200, 1, 255, Request.Form("title")) cmd.Parameters.Append cmd.CreateParameter("@content", 201, 1, 10000, Request.Form("content")) cmd.Parameters.Append cmd.CreateParameter("@author_id", 3, 1, , Session("user_id")) cmd.Execute Response.Redirect "nzcms_bq.asp?msg=success" End If

注意:cmd.Parameters.Append显式声明参数类型(200=adVarChar,201=adLongVarChar,3=adInteger)和长度,彻底阻断SQL注入。GETDATE()由SQL Server执行,避免客户端时间篡改。这种写法在ASP项目中并不普遍,说明该系统开发者具备较强的安全意识。

4. 部署调试与IIS 6.0兼容性关键配置

4.1 IIS 6.0虚拟目录设置与脚本映射验证

该系统针对Windows Server 2003 + IIS 6.0环境优化,部署时需确认以下三项:

配置项正确值错误表现验证命令
主目录执行权限“脚本和可执行文件”403.14错误(目录浏览被禁)cacls "C:\Inetpub\wwwroot\nzcms" /T /E /G "IIS_WPG":R
ASP脚本映射.aspC:\WINDOWS\system32\inetsrv\asp.dll404.2错误(MIME类型未注册)cscript adsutil.vbs get w3svc/1/root/ScriptMaps
默认文档index.asp必须在首位显示IIS默认欢迎页而非系统首页cscript adsutil.vbs get w3svc/1/root/DefaultDoc

提示:adsutil.vbs位于C:\Inetpub\AdminScripts\,是IIS 6.0原生管理工具。执行get w3svc/1/root/ScriptMaps后,检查输出中是否存在.asp映射行,且路径指向asp.dll。若缺失,需手动添加:cscript adsutil.vbs set w3svc/1/root/ScriptMaps ".asp,C:\WINDOWS\system32\inetsrv\asp.dll,5,GET,HEAD,POST,TRACE"

4.2 常见报错定位与On Error Resume Next的双刃剑用法

系统大量使用On Error Resume Next(见nzcms_sql.asax),这是ASP时代处理COM组件异常的惯用手法,但会掩盖真实错误。调试时需临时注释:

' nzcms_sql.asax 原始片段 On Error Resume Next Set conn = Server.CreateObject("ADODB.Connection") conn.Open connStr If Err.Number <> 0 Then Response.Write "数据库连接失败:" & Err.Description Response.End End If On Error GoTo 0 ' 恢复错误中断

关键调试步骤:

  1. global.asa中启用Application("debug") = True
  2. 修改nzcms_2.asp,在IP校验失败时追加日志:
    If Not isAllowed Then Dim fso, logFile Set fso = Server.CreateObject("Scripting.FileSystemObject") Set logFile = fso.OpenTextFile("C:\Inetpub\wwwroot\nzcms\logs\access.log", 8, True) logFile.WriteLine Now() & " | BLOCKED | " & clientIP & " | " & Request.ServerVariables("URL") logFile.Close Response.Status = "403 Forbidden" Response.Write "<h1>访问被拒绝</h1>..." Response.End End If
  3. 检查IIS日志%SystemDrive%\inetpub\logs\LogFiles\W3SVC1\,比对cs-uri-stemsc-status字段,确认是403还是500错误。

4.3asp:gridview列中的数据怎么换行问题的本地化解决方案

虽然该系统未使用.NET的GridView,但list.asp中表格单元格内容过长时同样面临换行需求。标准做法是在CSS中设置:

<style> .case-item h3 { word-break: break-all; white-space: pre-line; } </style>

但ASP环境常需服务端预处理。nzcms_dna.asp提供WrapText函数:

Function WrapText(text, maxLength) Dim result, i, lenText result = "" lenText = Len(text) For i = 1 To lenText If i Mod maxLength = 1 And i > 1 Then result = result & "<br>" result = result & Mid(text, i, 1) Next WrapText = result End Function

list.asp中调用:

<td><%= WrapText(Server.HTMLEncode(rs("title")), 20) %></td>

此函数按字符数强制换行,比CSS更可控,适用于IE6等老旧浏览器——这正是公安内网环境的真实约束。

5. 安全加固与IP限制策略的演进式优化技巧

5.1 从硬编码白名单到XML配置的平滑迁移

data.asax的硬编码方式不利于运维。可创建ip_whitelist.xml

<?xml version="1.0" encoding="GB2312"?> <whitelist> <ip>10.128.1.5</ip> <ip>10.128.1.12</ip> <subnet>10.128.3.0/24</subnet> <subnet>10.128.4.0/24</subnet> </whitelist>

并在nzcms_dna.asp中添加加载函数:

Function LoadIPListFromXML() Dim xmlDoc, ipNodes, subnetNodes, i, list Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM") xmlDoc.Async = False xmlDoc.Load Server.MapPath("ip_whitelist.xml") Set ipNodes = xmlDoc.SelectNodes("//ip") Set subnetNodes = xmlDoc.SelectNodes("//subnet") ReDim list(ipNodes.Length + subnetNodes.Length - 1) For i = 0 To ipNodes.Length - 1 list(i) = ipNodes(i).Text Next For i = 0 To subnetNodes.Length - 1 list(ipNodes.Length + i) = subnetNodes(i).Text Next LoadIPListFromXML = list End Function

然后在data.asax中替换为:

<% Dim g_IPList g_IPList = LoadIPListFromXML() %>

提示:Microsoft.XMLDOM在IIS 6.0默认可用,无需额外安装。GB2312编码确保中文注释正常读取。此改造零侵入现有逻辑,仅替换数据源。

5.2 日志审计增强:记录IP校验全过程

nzcms_2.asp的校验逻辑末尾添加审计日志:

' 校验完成后追加 Dim auditLog auditLog = Now() & "|" & clientIP & "|" & isAllowed & "|" & Request.ServerVariables("HTTP_USER_AGENT") & "|" & Request.ServerVariables("URL") & vbCrLf Dim fso, logFile Set fso = Server.CreateObject("Scripting.FileSystemObject") Set logFile = fso.OpenTextFile(Server.MapPath("logs\ip_audit.log"), 8, True) logFile.Write auditLog logFile.Close

生成的日志格式为:

2022-04-30 14:22:18|10.128.2.33|True|Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)|/nzcms/manage_web.asp 2022-04-30 14:23:05|192.168.1.100|False|curl/7.58.0|/nzcms/index.asp

配合Windows自带的findstr命令可快速分析:

findstr "False" C:\Inetpub\wwwroot\nzcms\logs\ip_audit.log | findstr "192.168"

精准定位非法扫描源。

5.3 应急熔断:nzcms_sql.asax中的数据库连接池保护

nzcms_sql.asax定义了连接池超时与重试机制:

' nzcms_sql.asax Const MAX_CONN_ATTEMPTS = 3 Const CONN_TIMEOUT = 15 ' 秒 Function GetDBConnection() Dim conn, attempts, startTime Set conn = Server.CreateObject("ADODB.Connection") attempts = 0 Do While attempts < MAX_CONN_ATTEMPTS On Error Resume Next conn.Open connStr, "", "", 64 ' adConnectUnspecified If Err.Number = 0 Then GetDBConnection = conn Exit Function End If attempts = attempts + 1 If attempts < MAX_CONN_ATTEMPTS Then WScript.Sleep 1000 ' 等待1秒后重试 End If Loop ' 三次失败后返回空连接,业务层需处理 Set GetDBConnection = Nothing End Function

64标志位(adConnectUnspecified)启用连接池,WScript.Sleep避免雪崩式重连。当数据库短暂不可用时,系统降级为只读(IP校验仍生效),保障核心访问控制不中断。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 4:19:33

基于MobileNet的花朵识别系统:从模型选型到Web部署全流程解析

1. 项目整体拆解与方案选型1.1 为什么是MobileNet&#xff1a;毕业设计选型的第一课每年到毕业季&#xff0c;计算机相关专业的学生都在纠结同一个问题&#xff1a;做什么题目既能顺利通过答辩&#xff0c;又不至于把自己折腾到脱发&#xff1f;花朵识别系统这个名字出现的频率…

作者头像 李华
网站建设 2026/9/16 4:19:03

海康威视SDK与Qt集成:实时预览Demo核心解析

简介&#xff1a;一套基于Qt框架的海康威视摄像头预览Demo&#xff0c;面向视频监控与Qt开发者&#xff0c;演示设备实时预览与播放。压缩包共55个文件&#xff0c;约9.08MB&#xff0c;包含dll动态库、lib导入库、exe可执行程序以及cpp/h源码&#xff0c;并附带pro工程文件和u…

作者头像 李华
网站建设 2026/9/16 4:18:17

路径之谜:DFS与剪枝破解行列计数搜索题

最近刷题时碰上一个特别有意思的搜索题&#xff0c;题目就叫“路径之谜”。给定一张 n x n 的棋盘&#xff0c;骑士从左上角出发&#xff0c;每一步只能上下左右移动&#xff0c;最终要走到右下角。奇怪的是&#xff0c;题目不问你“有多少条路径”&#xff0c;也不问你“最短路…

作者头像 李华
网站建设 2026/9/16 4:17:02

悬浮 Prompt 工具:让 Claude Code 与 Codex 的 CLI 交互效率倍增

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 4:16:58

OLT远程升级ONU固件全攻略:中兴C300、华为5680T、烽火AN5516实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 4:16:48

一天搭建OpenStack云平台:DevStack实操指南

有人问我&#xff0c;一天之内能不能把云平台搭起来&#xff0c;还能在上面顺利开出第一台虚拟机&#xff1f;我的回答是&#xff1a;能&#xff0c;但有明确的前提。你要是奔着生产环境那种多节点、高可用、带存储和网络虚拟化全家桶去的&#xff0c;那我劝你直接放弃这个念头…

作者头像 李华