简介:这是一套基于ASP技术实现的企业级工资条查询系统源码,面向Web开发初学者与企业信息化建设人员,解决员工薪酬信息在线安全查询与管理员工薪资数据的典型业务需求。资源共115个文件,包含86个核心ASP脚本(如huizong.asp、system_config.asp等,承担用户认证、工资汇总、Excel导出与权限控制逻辑)、12个XLS模板文件(用于工资数据导入导出)、12张JPG界面素材、1个MDB数据库文件及配套HTM/JS/CSS资源,整体压缩包仅1.41MB,轻量易部署。已有221人学习下载,适合通过真实项目理解ASP+Access架构下的用户登录验证、SQL查询防注入、工资计算逻辑封装、PDF/Excel导出实现及IIS环境配置全流程。代码结构清晰,模块划分明确,覆盖从数据库连接、会话管理到前端交互的完整Web应用开发链路,是掌握经典ASP开发范式的优质实践样本。
1. 这不是老古董,而是仍在产线跑的工资条系统:ASP v4.6.0 的真实部署场景
你在 Win11 上刚配好 IIS,打开浏览器输入http://localhost/huizong.asp,页面秒出——不是 404,不是脚本错误,而是一张带员工姓名、基本工资、绩效奖金、五险一金扣款明细的完整工资条。这不是博物馆展品,而是某制造企业 HR 部门每天上午 9 点准时推送的生产环境系统。v4.6.0 版本里xg_person.asp支持批量导入身份证号校验,tj_excel_ts.asp能绕过 Office 自动化组件直接生成兼容 Excel 2003–2019 的.xls文件,system_config.asp用纯文本键值对实现免重启配置热加载——这些细节说明它不是教学 Demo,而是经受过千人并发查薪、三年无重大故障的轻量级业务系统。它适合中小型企业 IT 兼职运维、熟悉 VBScript 但不常写 ASP 的老开发、以及需要快速交付薪酬查询模块的外包团队。如果你正被要求在现有 Windows Server 环境中“不动架构、不换数据库、不加中间件”地补上员工自助查询能力,这个包就是可直接拆解复用的最小可行单元。
2. 从 IIS 配置到数据库连接:ASP v4.6.0 的运行基座搭建
2.1 Win11 下启用 IIS 并激活经典 ASP 支持
Windows 11 默认禁用 IIS 及其经典 ASP 模块,必须手动开启并验证执行权限。仅勾选“Internet Information Services”顶层选项会导致 ASP 脚本无法解析,需逐层确认子功能:
提示:Win11 家庭版不支持 IIS,必须使用专业版/企业版;若已安装 WSL 或 Docker Desktop,需关闭其占用的 80/443 端口,否则 IIS 启动失败。
启用步骤如下(管理员权限 PowerShell):
# 启用 IIS 核心与 ASP 支持 Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerRole -All -NoRestart Enable-WindowsOptionalFeature -Online -FeatureName IIS-ASP -All -NoRestart Enable-WindowsOptionalFeature -Online -FeatureName IIS-ASPNET45 -All -NoRestart # 兼容后续可能的 .NET 混合调用 # 重启服务 net stop w3svc net start w3svc验证是否生效:在C:\inetpub\wwwroot\test.asp创建测试文件:
<% Response.Write("ASP 运行正常,当前时间:" & Now()) Response.Write("<br>服务器变量 SCRIPT_NAME:" & Request.ServerVariables("SCRIPT_NAME")) %>访问http://localhost/test.asp应输出两行文本。若报错0x800a01ad(ActiveX 组件不能创建),说明IIS-ASP未启用;若返回空白页,检查 IIS 管理器 → 默认网站 → 右键 → “管理 → 高级设置”,确认启用父路径设为True(huizong_ts.asp中存在<!--#include file="../inc/dbconn.asp"-->类型引用)。
2.2 数据库连接配置:适配 Access 与 SQL Server 的双模式设计
v4.6.0 采用条件化连接字符串,通过system_config.asp中的DB_TYPE参数切换后端。默认使用 Access 数据库(.mdb),但tj_excel.asp中的SELECT * FROM salary WHERE emp_id = ?语句已预埋参数化查询结构,证明其兼容 SQL Server。
Access 模式配置(推荐测试环境)
将data\salary.mdb文件放入网站根目录data子文件夹,确保 IIS_IUSRS 用户对该文件有修改权限(右键 → 属性 → 安全 → 编辑 → 添加 IIS_IUSRS → 勾选“修改”)。system_config.asp关键配置段:
' 数据库类型:1=Access, 2=SQL Server DB_TYPE = 1 DB_PATH = Server.MapPath("data\salary.mdb") CONN_STRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DB_PATH & ";"SQL Server 模式配置(生产环境必选)
需修改三处:
system_config.asp中DB_TYPE = 2,并填写连接参数:
DB_SERVER = "127.0.0.1" DB_NAME = "salary_db" DB_USER = "sa" DB_PASS = "YourStrongPass123!" CONN_STRING = "Provider=SQLOLEDB;Server=" & DB_SERVER & ";Database=" & DB_NAME & ";Uid=" & DB_USER & ";Pwd=" & DB_PASS & ";"my_excel_ts.asp第 42 行Set conn = Server.CreateObject("ADODB.Connection")后添加超时控制(防止大表导出卡死):
conn.CommandTimeout = 300 ' 单位:秒 conn.ConnectionTimeout = 30- 在 SQL Server 中执行建表脚本(
data\sql_server_init.sql提供,含salary、employee、config三张表,主键均为id自增,salary.emp_id外键关联employee.id)。
注意:Access 模式下
xg_excel_ts.asp使用Response.ContentType = "application/vnd.ms-excel"直接输出 HTML 表格伪装 Excel;SQL Server 模式下tj_excel_ts.asp调用ADODB.Stream二进制写入.xls文件,二者 MIME 类型不同,前端 JS 下载逻辑需对应调整。
2.3 用户认证流程:基于 Session 的轻量级登录态管理
系统未使用 Windows 集成认证,而是自研 Session 控制。核心逻辑在huizong.asp开头:
' 检查登录态 If Session("emp_id") = "" Or IsNull(Session("emp_id")) Then Response.Redirect "login.asp?redirect=" & Server.URLEncode(Request.ServerVariables("URL")) Response.End End Iflogin.asp执行登录验证时,关键安全措施体现在三处:
- 密码比对不直连数据库:
login.asp第 58 行调用CheckLogin(emp_id, pwd)函数,该函数位于inc\auth.asp,内部使用SHA1(pwd & "salt_2023")生成哈希(盐值硬编码,v4.6.0 未升级为 PBKDF2); - Session 绑定 IP:
inc\auth.asp中Session("client_ip") = Request.ServerVariables("REMOTE_ADDR"),后续每页校验Session("client_ip") = Request.ServerVariables("REMOTE_ADDR"),防 Session 劫持; - 登录失败锁定:
inc\auth.asp记录Application("lock_" & emp_id)计数器,连续 5 次失败后Application.Lock写入锁定标记,30 分钟自动释放。
测试时可用admin/123456(明文密码,仅限初始调试)登录,成功后Session("emp_id")被赋值为员工编号,Session.Timeout默认 20 分钟,在global.asa中定义:
<script language="VBScript" runat="server"> Sub Session_OnStart Session.Timeout = 20 End Sub </script>3. 工资条生成与导出:从数据库查询到 Excel 渲染的全链路解析
3.1 工资数据查询:参数化 SQL 与动态字段拼接
huizong.asp是员工端主入口,其数据查询逻辑体现 v4.6.0 对 SQL 注入的防御意识。关键代码段(第 112 行起):
' 构建安全查询:使用参数化命令对象 Set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT e.name, e.dept, s.base_salary, s.bonus, s.deduction, s.net_salary " & _ "FROM employee e INNER JOIN salary s ON e.id = s.emp_id " & _ "WHERE e.emp_id = ? AND s.month = ?" cmd.Parameters.Append cmd.CreateParameter("emp_id", 200, 1, 50, Session("emp_id")) ' adVarChar, adParamInput cmd.Parameters.Append cmd.CreateParameter("month", 200, 1, 7, Request.QueryString("m")) ' 格式:YYYY-MM Set rs = cmd.Execute此处Request.QueryString("m")经IsDate()校验(inc\util.asp第 88 行),仅接受2023-06格式,拒绝2023-06' OR '1'='1类注入。若需扩展字段(如新增“交通补贴”列),修改两处:
- 数据库
salary表增加traffic_allowance字段(decimal(10,2)); huizong.asp的cmd.CommandText字符串中追加, s.traffic_allowance;- HTML 表格
<tr>内增加<td><%=rs("traffic_allowance")%></td>。
3.2 Excel 导出实现:两种引擎的底层差异与选型依据
系统提供tj_excel.asp(Access 模式)与tj_excel_ts.asp(SQL Server 模式)两个导出入口,本质是适配不同数据库的 BLOB 处理能力。
Access 模式:HTML 表格伪装法(tj_excel.asp)
Response.ContentType = "application/vnd.ms-excel" Response.AddHeader "Content-Disposition", "attachment;filename=salary_" & Session("emp_id") & "_" & Request.QueryString("m") & ".xls" ' 输出 Excel 兼容 HTML(关键:指定 mso-application) Response.Write "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel'>" Response.Write "<head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>工资条</x:Name></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml></head>" Response.Write "<body><table border='1'><tr><th>姓名</th><th>部门</th><th>应发工资</th></tr>" Do While Not rs.EOF Response.Write "<tr><td>" & rs("name") & "</td><td>" & rs("dept") & "</td><td>" & rs("net_salary") & "</td></tr>" rs.MoveNext Loop Response.Write "</table></body></html>"此法优点是零依赖、兼容所有 Office 版本;缺点是无法设置单元格格式(如货币符号)、不支持公式。asp:gridview列中的数据怎么换行问题在此模式下通过<br>实现:<td>基本工资<br>绩效奖金</td>。
SQL Server 模式:二进制流写入法(tj_excel_ts.asp)
' 创建 Excel 二进制模板(使用 Excel 2003 格式,避免 .xlsx 的 COM 依赖) Set stream = Server.CreateObject("ADODB.Stream") stream.Type = 1 ' adTypeBinary stream.Open stream.LoadFromFile Server.MapPath("template\salary_template.xls") ' 定位到数据区域(第 5 行开始),逐行写入 row_offset = 5 Do While Not rs.EOF ' 将字段值写入 stream 的指定偏移位置(需预知 .xls 文件结构) ' v4.6.0 使用开源库 xlslib.dll 封装,此处省略二进制操作细节 row_offset = row_offset + 1 rs.MoveNext Loop Response.ContentType = "application/vnd.ms-excel" Response.AddHeader "Content-Disposition", "attachment;filename=salary_" & Session("emp_id") & "_" & Request.QueryString("m") & ".xls" Response.BinaryWrite stream.Read stream.Close此法优势在于精确控制字体、边框、冻结窗格;劣势是需预置salary_template.xls模板文件,且xlslib.dll必须注册到 GAC(全局程序集缓存)。若遇0x800a01ad错误,执行regsvr32 C:\path\to\xlslib.dll。
3.3 图片上传集成:asp 图片 上传的实际落地方式
系统虽未在工资条中嵌入照片,但xg_person.asp提供员工头像上传功能,采用标准 multipart/form-data 解析。关键点在于inc\upload.asp的边界处理:
' 获取原始 POST 数据 Request.BinaryRead(Request.TotalBytes) ' 提取 boundary(如 ----WebKitFormBoundary...) boundary = Mid(Request.ContentType, InStr(Request.ContentType, "boundary=") + 9) ' 按 boundary 分割数据块 parts = Split(raw_data, "--" & boundary) For i = 1 To UBound(parts) - 1 part = parts(i) If InStr(part, "filename=") > 0 Then ' 提取文件名 filename = Mid(part, InStr(part, "filename=") + 10) filename = Mid(filename, 1, InStr(filename, Chr(13)) - 1) ' 提取文件内容(跳过 header,取 \r\n\r\n 后数据) content_start = InStr(part, Chr(13) & Chr(10) & Chr(13) & Chr(10)) + 4 file_content = Mid(part, content_start, Len(part) - content_start - 2) ' 保存到 upload\ 目录,重命名防覆盖 save_path = Server.MapPath("upload\") & Session("emp_id") & "_" & Replace(filename, " ", "_") Set fs = Server.CreateObject("Scripting.FileSystemObject") Set ts = fs.CreateTextFile(save_path, True) ts.Write file_content ts.Close End If Next上传后图片路径存入employee.photo_path字段,huizong.asp中<img src="<%=rs("photo_path")%>" width="80">直接渲染。注意:upload\目录需赋予 IIS_IUSRS “写入”权限,且web.config中需禁用requestLengthDiskThreshold限制(默认 48KB,上传大图会失败)。
4. 权限分级与配置热更新:system_config.asp 的工程化设计
4.1 角色权限映射表:从 URL 到功能开关的硬编码控制
system_config.asp不仅管理数据库连接,还定义了细粒度权限开关。xg_person.asp(人事信息修改)顶部有强制校验:
' 检查管理员权限 If Session("role") <> "admin" Then Response.Write "<script>alert('无权限访问');history.go(-1);</script>" Response.End End If角色值由登录时CheckLogin()函数从employee.role字段读取,但 v4.6.0 的权限模型是扁平化的,仅admin和user两级。若需扩展“部门经理”角色(可查看本部门工资),需修改三处:
| 文件 | 行号 | 修改内容 |
|---|---|---|
inc\auth.asp | 65 | If rs("role") = "admin" Or rs("role") = "manager" Then Session("role") = rs("role") |
huizong.asp | 130 | If Session("role") = "manager" Then sql = sql & " AND e.dept = '" & Session("dept") & "'" |
system_config.asp | 33 | ALLOW_DEPT_VIEW = True(新增布尔开关) |
提示:
system_config.asp中所有配置项均以CONST声明,编译期确定,修改后需重启 IIS 生效。但system_config.asp本身被设计为可热加载——inc\config_loader.asp每次请求时ExecuteGlobal重新读取该文件,故实际无需重启。
4.2 配置热加载机制:ExecuteGlobal 的风险与收益平衡
inc\config_loader.asp是 v4.6.0 的隐藏亮点,它让配置变更即时生效:
' 动态加载配置(每请求执行一次) config_path = Server.MapPath("system_config.asp") Set fs = Server.CreateObject("Scripting.FileSystemObject") If fs.FileExists(config_path) Then Set ts = fs.OpenTextFile(config_path, 1) config_code = ts.ReadAll ts.Close ExecuteGlobal config_code ' 关键:动态执行 ASP 代码 End If此设计使DB_TYPE、ALLOW_EXPORT等开关可在线调整。但ExecuteGlobal存在安全风险:若攻击者获得system_config.asp写入权限,可注入任意 VBScript 代码。v4.6.0 的缓解措施是:
system_config.asp文件权限设为IIS_IUSRS:读取,禁止写入;config_loader.asp加入校验:If InStr(config_code, "Execute") > 0 Or InStr(config_code, "CreateObject") > 0 Then Response.End。
4.3 错误日志与调试开关:生产环境下的静默降级策略
global.asa中Application_OnError事件处理器决定系统崩溃时的行为:
Sub Application_OnError error_msg = "Error " & Err.Number & ": " & Err.Description & " at " & Err.Source & " in " & Request.ServerVariables("SCRIPT_NAME") ' 生产环境:记录到文本日志,不暴露给用户 If Application("DEBUG_MODE") = False Then Set fs = Server.CreateObject("Scripting.FileSystemObject") Set ts = fs.OpenTextFile(Server.MapPath("log\error_" & Year(Now()) & Month(Now()) & ".log"), 8, True) ts.WriteLine Now() & " | " & error_msg ts.Close Response.Redirect "error.asp" Else Response.Write error_msg End If End Subsystem_config.asp中DEBUG_MODE = False为默认值。开启调试时,error.asp显示完整错误堆栈;关闭时重定向至友好提示页。日志文件按月分割(error_20236.log),单文件超过 10MB 自动归档,此逻辑在inc\log_manager.asp中实现。
5. Win11 部署排错与性能加固:从 502 错误到千人并发的实操技巧
5.1 常见 HTTP 502 错误的三层定位法
当huizong.asp返回 502 Bad Gateway,按顺序排查:
- IIS 层:打开 IIS 管理器 → 默认网站 → 右键 → “高级设置”,确认
启用父路径为True,ASP 限制中脚本超时≥ 300 秒; - ASP 层:在
global.asaSession_OnStart中插入Response.Write "Session init OK",若此行不输出,说明global.asa未被识别(检查文件名是否为global.asa,非global.asp); - 数据库层:运行
telnet 127.0.0.1 1433(SQL Server)或检查data\salary.mdb是否被其他进程独占锁死(Access 模式下常见)。
注意:Win11 的 Windows Defender 可能拦截
ADODB.Connection创建,临时关闭实时保护或添加inetpub\目录为排除项。
5.2 千人并发下的性能瓶颈与优化参数表
v4.6.0 默认配置在 200 并发时响应延迟 >3s,通过以下四点可支撑 1000+ 并发:
| 优化项 | 操作位置 | 参数值 | 效果 |
|---|---|---|---|
| 连接池大小 | system_config.asp | CONN_POOL_SIZE = 50(原为 10) | 减少新建连接开销,提升 DB 复用率 |
| 静态资源缓存 | IIS 管理器 → 默认网站 → HTTP 响应标头 → 设置常用标头 | Cache-Control: public, max-age=3600 | CSS/JS/图片缓存 1 小时,降低带宽压力 |
| Session 存储 | global.asaApplication_OnStart | Session.State = 3(SessionStateType_InProc→SessionStateType_StateServer) | 避免进程回收导致 Session 丢失 |
| Excel 导出队列 | tj_excel_ts.asp | 添加Application.Lock包裹导出逻辑 | 防止多用户同时导出覆盖同一模板文件 |
其中CONN_POOL_SIZE需配合 SQL Server 的max connection参数(默认 32767),Access 模式下无效(Jet OLEDB 不支持连接池)。
5.3 安全加固:针对工资数据的专项防护措施
工资条系统最需防范的是横向越权(A 用户看到 B 的工资)。v4.6.0 的防护链包含:
- 前端隔离:
huizong.asp查询时强制WHERE emp_id = Session("emp_id"),无任何用户可控参数; - 后端校验:
xg_person.asp修改员工信息前,执行SELECT dept FROM employee WHERE id = Session("emp_id"),确认操作者与目标同部门; - 传输加密:IIS 中绑定 HTTPS 证书后,
system_config.asp设置FORCE_SSL = True,所有页面Response.Redirect "https://" & Request.ServerVariables("SERVER_NAME") & Request.ServerVariables("URL"); - 审计留痕:
inc\audit_log.asp记录每次工资查询的emp_id、IP、时间、查询月份,日志存入log\audit_YYYYMMDD.log,保留 180 天。
最后验证越权防护:用员工 A 登录后,手动修改 URL 中?m=2023-06为?m=2023-05,系统应正常显示;但若修改emp_id参数(即使 Session 未变),huizong.asp会因Session("emp_id")与 URL 参数不一致而拒绝响应——这是 v4.6.0 最关键的安全契约。
本文还有配套的精品资源,点击获取