ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

老当益壮:ASP全能OA系统源码部署、改造与加固实战

老当益壮:ASP全能OA系统源码部署、改造与加固实战 简介一套基于ASP技术构建的全能OA办公系统源码包定位在企业内部日常办公场景面向需要学习经典Web开发模式或搭建公告、审批、文档流转等功能的开发者、运维人员和计算机专业学生。压缩包大小约4.89MB由于下载页未提供文件统计信息具体文件总数与明细暂时无法明确按同类项目惯例解压后通常会看到ASP页面、数据库脚本、web.config配置、样式脚本及说明文档分别承担页面逻辑、数据存储、运行参数、前端交互和部署引导。目前已有53人学习浏览适合作为ASP进阶项目或课程设计的参考资料。学习这套代码可以观察基于服务器端脚本的OA系统如何实现登录验证、角色权限、审批流程、信息发布等核心模块有助于理解早期ASP项目的分层和模块组织方式。实际部署时需准备IIS与SQL Server或Access数据库并留意数据库连接配置和旧版ASP在Windows新环境的兼容性在此基础上可根据企业需要做二次开发作为轻量级办公原型或课程设计素材。1. 一个二十年的老技术凭什么还能撑起企业级OA如果你在一家老牌制造企业或国企待过大概率见过这种场面Windows Server 2008 的机柜里跑着一个用了十几年的OA系统页面是表格布局地址栏里是 .asp?actionlogin 这样的参数。维护它的老工程师退休前留下一句“别动核心代码”就走人了。这套系统很可能就是基于 ASP 的全能 OA 办公系统——一个用 VBScript 写的、依赖 IIS 和 Access/SQL Server 的办公自动化全家桶。ASP 是微软 1996 年推出的服务器端脚本环境它的生命周期早已结束但沉淀在中小企业里的 ASP OA 系统还在线上运行。原因很现实换掉一套被部门用了十多年的审批流程比升级技术栈难得多。本文要讲的这个 .zip 压缩包就是这类系统的完整源码。它适合两类人一类是接手遗留系统、需要快速读懂并部署的运维工程师另一类是正在研究 ASP 架构设计、想理解老系统为什么能长命的开发人员。我会按解压、部署、改造、排错的真实路径把关键文件、参数和坑都拆开说。2. 解压后先看什么ASP OA 系统的目录结构与数据依赖拿到基于ASP的全能OA办公系统.zip后先别急着扔到 IIS 根目录。压缩包里的文件名虽然被处理成一个长数字串但还原后典型的老派 ASP 项目结构是有固定套路的。我一般会先按目录分组扫一遍判断它是纯脚本版还是带编译组件版。2.1 从入口文件反推系统架构最外层一定有default.asp或index.asp这是整个 OA 的入口。打开入口文件你会看到大量的!--#include fileinc/conn.asp--这样的包含指令。ASP 没有现代框架的包管理所有公共逻辑全靠 include 文件堆叠。常见的目录有目录/文件作用需要关注的细节/inc/或/include/数据库连接、函数库、页面头部尾部是否有conn.asp、config.asp/admin/后台管理模块通常单独一套登录权限/oa/业务模块公文、审批、日程按功能分子目录/upload/附件上传目录是否有上传组件调用/database/Access 的.mdb存放处检查是否可下载安全风险web.config早期 IIS 配置仅 IIS7里面常有假的配置实际靠 IIS 管理器如果解压后看到web.config先读一遍。很多老系统从 IIS6 迁移到 IIS7 后这个文件里只写了几个httpRuntime参数真正的虚拟目录权限还是在 IIS 管理器里配置的。2.2 数据库选型Access 还是 SQL Server老 ASP OA 的数据库有两种主流选型Access 的.mdb文件和 SQL Server 的.mdf/.ldf文件。这决定了你的部署难度。打开inc/conn.asp你会看到类似这样的连接代码% Dim conn, rs, connStr connStr ProviderMicrosoft.Jet.OLEDB.4.0;Data Source Server.MapPath(../database/oa.mdb) Set conn Server.CreateObject(ADODB.Connection) conn.Open connStr %这段代码用的是 Access 的 Jet OLE DB 提供程序。Data Source用了Server.MapPath把相对路径映射到服务器物理路径好处是换服务器不需要改绝对路径坏处是如果/database/目录没有做访问限制用户直接在浏览器输入http://你的域名/database/oa.mdb就能把数据库下载走。后面安全部分我会重点说这个。如果连接串长这样connStr ProviderSQLOLEDB;Data Source127.0.0.1;Initial CatalogOA_DB;User IDsa;Password...那就是 SQL Server 版本。SQLOLEDB 是微软老一代的 OLE DB 驱动在 Windows Server 2016 之后的系统上会出现兼容性警告建议换成新版驱动。但改驱动意味着改全站所有连接文件老系统如果没问题我建议先不动。2.3 全局包含文件与权限拦截逻辑ASP OA 的权限控制通常散落在两个地方一是每个页面前面包含的checklogin.asp二是后台管理页的checkadmin.asp。前者判断 Session 是否有效后者判断登录人角色。你会在每个业务页面的最顶部看到这三行!--#include file../inc/conn.asp-- !--#include file../inc/checklogin.asp-- % 页面逻辑从这里开始 %checklogin.asp的典型实现是% If Session(user_id) Then Response.Redirect login.asp?msgtimeout Response.End End If %注意这里用的是重定向而不是服务器跳转。如果用来做 API 接口客户端会收到 302 状态码。老系统的登录态基本不设过期时间IIS 的应用池回收后 Session 就丢了用户会频繁掉线这是后面部署时要调 IIS 运行时的原因。3. 部署实战在 Windows 11 的 IIS 上让 ASP OA 跑起来很多人在 Windows 11 上配置 IIS 去跑 ASP 老系统结果第一步就卡在功能没有启用。Win11 自带的 IIS 10 默认不安装 ASP 支持需要手动打开。3.1 启用 IIS 与 ASP 模块按Win R输入optionalfeatures在 Windows 功能对话框中勾选以下最小集Internet Information Services万维网服务 - 应用程序开发功能 - ASP万维网服务 - 常见 HTTP 功能 - 静态内容、默认文档万维网服务 - 运行状况和诊断 - HTTP 日志、请求监视如果要用 Access 数据库还需要勾选以下两项Internet Information Services - 万维网服务 - 应用程序开发功能 - ISAPI 筛选器应用程序管理 - IIS 管理脚本和工具可选方便命令行管理这里最容易漏掉的是“ASP”本身。很多人只装了 IIS结果访问 .asp 文件变成下载或 404。装好后打开 IIS 管理器在中间“功能视图”里能看到“ASP”图标说明模块已注册。3.2 创建站点并配置应用程序池我一般会给老系统单独建一个应用程序池.NET CLR 版本选“无托管代码”托管管道模式选“经典”。经典模式是为了兼容老 ASP 的 Session 和 Response 行为。站点物理路径指向解压后的目录比如D:\OA\。右键站点 - 编辑权限给IIS_IUSRS组完全控制权限老系统会有写文件的需求比如上传、写日志最小化权限下至少要给读写。接下来是几个进阶设置配置项位置推荐值说明启用父路径站点 ASP 功能 - 行为True老代码里大量使用../相对路径默认禁用会报 500脚本超时站点 ASP 功能 - 服务90-180 秒审批导出等长耗时操作需要并发限制应用程序池 - 回收固定时间间隔 1740避免凌晨回收导致 Session 全丢32 位应用程序应用程序池 - 高级设置True如果引用了 32 位 COM 组件如上传组件必须开3.3 处理数据库文件与连接串如果压缩包里带的是.mdb文件部署时把database目录放到站点下并修改inc/conn.asp里的路径。注意 IIS7 之后默认对.mdb文件不返回内容但保险起见我会在web.config或 IIS 请求筛选里显式禁止访问/database/目录。如果带的是 SQL Server 的.mdf需要把数据文件附加到 SQL Server。还有一种常见做法是用 SQL 脚本生产数据库脚本里通常包含建表语句和初始管理员数据。执行方式sqlcmd -S .\SQLEXPRESS -E -i oa_db.sql如果系统里没有 sqlcmd可以在 SQL Server Management Studio 里打开脚本后按 F5 执行。执行前注意检查脚本开头有没有USE [OA_DB]和GO分隔符老脚本经常漏掉。3.4 经典报错HTTP 500 与 Server.CreateObject 失败部署完后访问首页最常见的错误是“500 - 内部服务器错误”。这时先到事件查看器里看 ASP 相关日志。我总结了一个排查顺序1. IIS 管理器里打开 ASP 功能把“调试属性 - 向客户端发送错误”改为 True 2. 刷新页面如果看到具体错误行按行号查是哪个包含文件出错 3. 如果报 Server.CreateObject 失败检查组件注册regsvr32 某个.dll 4. 如果报数据库连接失败检查 OLEDB 驱动是否安装对于 Access 数据库Windows 11 上默认没有 Jet OLE DB 驱动因为 Office 2013 之后不再分发 32 位的 Microsoft.Jet.OLEDB.4.0。这时要么改用 Microsoft.ACE.OLEDB.12.0需要安装 Access Database Engine要么把数据库迁移到 SQL Server。前者安装后要确保应用程序池的 32 位设置和驱动位数匹配。4. 核心业务改造登录、角色权限与审批状态机部署能跑只是开始。真正让老 OA 适配新需求的是业务层改造。这三个模块是我在接手系统时必改的地方登录态、菜单权限、审批流。它们直接决定系统的安全性和可维护性。4.1 登录逻辑与 Session 加固老系统的登录脚本通常长这样% Dim u, p u Request.Form(username) p Request.Form(password) Set rs conn.Execute(SELECT * FROM users WHERE username u AND password p ) If rs.EOF Then Response.Write scriptalert(用户名或密码错误);history.back()/script Else Session(user_id) rs(user_id) Session(user_name) rs(user_name) Response.Redirect main.asp End If %这段代码最大的问题是 SQL 注入。u和p从表单直接拼进 SQL攻击者输入 OR 11就能绕过去。我在改造时最优先替换这段逻辑用参数化查询% Dim cmd, rs Set cmd Server.CreateObject(ADODB.Command) Set cmd.ActiveConnection conn cmd.CommandText SELECT user_id, user_name FROM users WHERE username? AND password? cmd.Parameters.Append cmd.CreateParameter(u, 200, 1, 50, Request.Form(username)) cmd.Parameters.Append cmd.CreateParameter(p, 200, 1, 50, Request.Form(password)) Set rs cmd.Execute If rs.EOF Then Response.Redirect login.asp?msgerror Else Session(user_id) rs(user_id) Session(user_name) rs(user_name) Response.Redirect main.asp End If %参数化改造后原来所有直接拼 SQL 的地方都要一并处理工作量不小。但 OA 系统的用户表一旦被脱库内部通讯录、组织结构、审批记录全部泄露这个代价远比改代码高。4.2 菜单权限的动态生成OA 的角色权限模型一般是用户 - 角色 - 菜单/操作权限。全能的说法就是指它覆盖了人事、行政、财务、项目等多套菜单。老做法是在main.asp里写死 if 判断新业务部门加一个菜单就要改代码。我建议改成基于字段的可见性控制。数据库里会有一张类似menu的表结构通常是CREATE TABLE menu ( menu_id INT PRIMARY KEY, parent_id INT, menu_name VARCHAR(50), href VARCHAR(200), role_ids VARCHAR(200) -- 逗号分隔的角色ID );ASP 里动态输出菜单时先查当前用户角色再过滤role_ids是否包含该角色% Set rs conn.Execute(SELECT * FROM menu WHERE parent_id0 AND role_ids LIKE % Session(role_id) % ORDER BY sort_no) Do While Not rs.EOF Response.Write lia href rs(href) rs(menu_name) /a/li rs.MoveNext Loop %这个方案的问题在于LIKE %不能用到索引但菜单表数据量很小性能不是瓶颈。真正要注意的是role_ids的格式如果角色 ID 是 1 和 11LIKE %1%会把 11 也匹配进来。我一般会把role_ids存成,1,3,这种带前后逗号的格式查询时用LIKE %,1,%。4.3 审批流用状态机替代散落的状态字段很多 ASP OA 的审批模块就是一张表加一个status字段状态用数字 0、1、2 表示。没有状态机概念时新加一个“已撤回”状态就要改所有判断逻辑。我参与改造过的系统里最乱的代码就是这种If status 1 Or status 3 Then 允许审批 ElseIf status 2 And is_admin True Then 管理员可以驳回 End If状态多了之后可维护性极差。推荐做法是抽出两张表审批单表和审批状态流转记录表。CREATE TABLE leave_request ( req_id INT PRIMARY KEY, req_user VARCHAR(20), status TINYINT, -- 0草稿 1部门审批 2总经理审批 3完成 4驳回 create_date DATETIME ); CREATE TABLE approval_flow ( flow_id INT IDENTITY PRIMARY KEY, req_id INT, from_status TINYINT, to_status TINYINT, action_user VARCHAR(20), action_date DATETIME, comment VARCHAR(500) );ASP 端提交审批动作时先查当前状态确认可执行的动作再更新主表状态同时插入流转记录。这个操作必须放在事务里% conn.BeginTrans Set rs conn.Execute(SELECT status FROM leave_request WHERE req_id reqId) currentStatus rs(status) If currentStatus 1 Then conn.Execute UPDATE leave_request SET status2 WHERE req_id reqId conn.Execute INSERT INTO approval_flow (req_id, from_status, to_status, action_user, action_date) VALUES ( reqId , 1, 2, sessionUserId , GETDATE()) Else Response.Write 当前状态不允许该操作 conn.RollbackTrans Response.End End If conn.CommitTrans %这里用了整型状态值但不建议直接用裸数字在代码里到处比较。可以在文件头用 Const 定义状态常量Const ST_DEPT 1 Const ST_GENERAL 2这样读代码时不需要回忆数字含义。状态机的好处是撤回、加签、会签这些新动作本质就是新增一组允许的状态跳转不影响原有逻辑。5. 图片上传与老系统性能优化的几个实用技巧最后一个实战章节我把最常遇到的 ASP OA 图片上传问题和性能优化放在一起说。因为这两块东西在招聘需求里很少被提起但线上环境十有八九会卡在这里。5.1 Web 方式上传无组件还是组件ASP 上传文件一直是个老话题。老系统里常见两种做法一是用第三方的ASPUpload、LyfUpload这类 COM 组件二是纯 ASP 代码解析二进制流。如果你在代码里看到Set upload Server.CreateObject(Persits.Upload)那就是组件版。这类组件在 64 位 Windows 上经常无法运行应用程序池必须开 32 位。在 Windows 11 上我建议优先用无组件上传把上传代码做成一个upload.asp包含文件输出文件名字段。无组件上传的代码网上很多核心思路是用Request.BinaryRead读原始字节流再按 multipart 边界切割。我改造时踩过的坑是中文文件名乱码解决方案是把文件名做一次编码转换fname Request.Form(fname) fname UTF2GB(fname) 自定义函数从UTF-8转GB23125.2 上传目录的路径安全上传文件如果放到/upload/下且服务器没有限制脚本执行攻击者上传一个.asp文件就能直接执行命令。这是老 OA 被挂马的高发原因。我会做两层防护configuration system.webServer handlers add nameNoScriptUpload pathupload/*.asp verb* typeSystem.Web.StaticFileHandler / /handlers /system.webServer /configuration上面这段web.config将 upload 下的.asp请求交给静态文件处理器处理。更稳妥的做法是在 IIS 管理器里取消上传目录的脚本访问权限右键目录 - 处理程序设置 - 编辑功能权限取消“脚本”。这样即使被传了.asp文件请求也只当作静态资源不会执行。5.3 SQL 注入的统一防线除了参数化改造还有一个低成本方案写一个全局 include 文件过滤所有请求参数。在conn.asp里放开头加% Function SafeRequest(name) Dim val val Request.Form(name) If val Then val Request.QueryString(name) SafeRequest Replace(val, , ) End Function %这个函数用单引号转义来拦截注入但注意它不能替代参数化查询只能作为历史系统的临时加固。真正的做法还是逐步把关键查询迁到参数化模式上去。5.4 减少重复连接把数据库连接改为延迟打开老系统性能差的最大原因是每个页面都创建连接页面多了之后 Access 的锁冲突非常明显。我在审代码时发现很多页面开头就打开连接但只有一两处查询。可以改成需要用的时候再打开连接Function getConn() If conn Is Nothing Then Set conn Server.CreateObject(ADODB.Connection) conn.Open connStr End If Set getConn conn End Function同时每个页面结束前显式关闭连接并释放对象% If IsObject(rs) Then rs.Close Set rs Nothing End If If IsObject(conn) Then conn.Close Set conn Nothing End If %Access 数据库多用户并发写入时如果配置了错误的锁模式会出现“操作被另一个用户锁定”的提示。可以在连接串里追加;Lock Type3;这是客户端游标锁适合小并发场景。如果是 SQL Server重点检查查询是否有缺失索引比如审批记录表按req_id查没有索引就会全表扫描。5.5 用最少成本验证改造效果改造完建议先用模拟请求压一下登录和审批提交两个接口。老系统没有压测工具可以用 PowerShell 的循环请求观察响应时间1..20 | ForEach-Object { $r Invoke-WebRequest -Uri http://localhost/oa/default.asp -UseBasicParsing Write-Host $_ $($r.StatusCode) $($r.Content.Length) }如果 StatusCode 全部 200Content.Length 稳定说明基本通畅。接着用类似方式测一个查询型的页面比如待办列表如果响应时间超过 3 秒就要去数据库里看那两条主要查询的IO统计。这样的验证方式不依赖工具链在任何一台 Windows 服务器上都能跑。以上这些动作做完这套基于 ASP 的全能 OA 办公系统就能在一台普通的 Windows 11 或 Windows Server 机器上稳定运行。代码是二十年前的但业务逻辑和优化思路放到今天依然不过时这也是为什么很多企业宁可守着老系统也不愿意推倒重来的原因。本文还有配套的精品资源点击获取
返回列表