news 2026/9/12 19:17:10

老式ASP+Access报修系统:部署、流程与安全改造实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
老式ASP+Access报修系统:部署、流程与安全改造实战

简介:一款基于ASP的网页版报修系统,面向企事业单位后勤、学校及物业等场景,帮助管理员快速搭建线上报修平台,让用户在线提交维修申请并跟踪处理进度。压缩包共52个文件,整体仅793KB,以ASP动态页面为主,辅以JS交互脚本、CSS样式表、HTM页面和JPG/GIF图片素材,另有IIS配置工具与使用说明,解压后即可按文档部署调试。系统覆盖用户注册登录、报修单填写、后台管理、留言反馈等常用环节,模块划分清晰,适合有ASP基础的学习者参考其前后台实现思路;描述中提到功能强大、易上手,但也存在一些可优化之处,因此也适合二次开发时对照改进。已有88人学习下载,对想了解传统ASP报修系统结构或需要轻量级内网报修方案的用户,是一份实用的入门资料。

1. 报修系统baoxiu.rar:一套仍在运行的ASP+Access报修台

解压开baoxiu.rar,里面不是漂亮的 Ant Design 页面,也没有前后端分离的工程结构,而是一排排.asp.js.css。这是一套典型的 Windows IIS + ASP + Access 老式网上报修系统,放在企业内网或者学校机房,够用但不完美。它的核心链路很短:用户注册登录,提交维修单,管理员在admin/houtai.asp里看到待处理列表,编辑状态、填写处理意见,用户再回首页看结果。强在逻辑直白,所有处理过程都摊在代码里;弱在 SQL 拼接、验证码形同虚设、Access 并发写时容易报错。但正因为老,反而适合用来拆解报修系统的流程设计,或者作为内部小工具快速改一版上线。下面从部署到改坑,一层层说透。

2. 解压与部署:IIS下配置baoxiu报修系统的目录权限与数据库连接

2.1 先看清压缩包里的文件布局

baoxiu.rar解压后,根目录下是站点主文件,admin目录装后台,images放图片,js里是count.jsdate.js这类前端脚本。核心文件的作用先列出来,方便后面对照:

文件角色说明
conn.asp数据库连接几乎每个页面都会 include,负责打开 Access 连接
conn2.asp第二连接用于后台统计、按日期查询等独立数据链路
index.asp前台首页展示报修入口、公告和维修状态
weixiu.asp报修提交接收表单并写入维修记录
login.asp登录校验用户密码,写入 session
reg.asp注册新用户注册,配合regsubmit.asp完成落库
admin/houtai.asp后台首页管理员登录后的待办列表
admin/lyedit.asp维修单编辑修改内容、转状态、写处理结果
admin/dele_ly.asp维修单删除按 id 删除记录
admin/adduser.asp用户管理新增后台账号或普通用户
style.css/type.css样式控制整体界面布局和表单样式

老系统没有web.config,也没有applicationHost.config级别的配置,所以部署重点全在 IIS 设置和文件权限上。

2.2 在 IIS 上部署:让 .asp 正常执行

先假设你已经把目录复制到C:\inetpub\wwwroot\baoxiu。在 IIS 管理器里右键创建应用程序,或者直接作为虚拟目录映射过去。关键点有两个:脚本执行权限必须选“纯脚本”,默认应用程序池要支持 ASP。如果 IIS 还没装 ASP 模块,可以先用 PowerShell 确认:

Get-WindowsFeature Web-ASP

状态是Installed就可以继续。如果缺失,补装后重置 IIS:

Install-WindowsFeature Web-ASP iisreset

这里Web-ASP指的是 IIS 的 ASP 功能角色,不是某个第三方组件。装完后要把站点根目录的权限放开给IIS_IUSRS,否则访问时会弹 500.19 或“无法识别该 URI 方案”。右键目录 -> 安全 -> 编辑,给IIS_IUSRS至少“读取和执行”权限。

2.3 conn.asp:Access 连接字符串的参数拆解

这套系统里几乎所有页面顶部都会 include 一个conn.asp,它负责创建 ADODB.Connection。老代码典型写法:

<% Dim conn, db, connstr db = "data/baoxiu.mdb" connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(db) Set conn = Server.CreateObject("ADODB.Connection") conn.Open connstr %>

db是数据库相对站点根目录的路径,Server.MapPath会把虚拟路径映射成物理路径。注意Provider有两种:Jet 4.0 对应 Access 2003 及以下的.mdb文件;如果你拿到的数据库是.accdb格式,要改用Microsoft.ACE.OLEDB.12.0。在 64 位操作系统上,老系统经常报“未在本地计算机上注册 Microsoft.Jet.OLEDB.4.0”,此时不需要换代码,直接到 IIS 应用程序池里把“启用 32 位应用程序”设为True,或者单独装 Access Database Engine 2010 的 64 位版本。

conn2.asp里一般也写着类似的连接串,它存在的意义是和conn.asp保持两个独立连接。我在查询日期页面看到它被part_star.asp调用,避免高频读取阻塞主连接写库。如果你完全不需要双连接,可以统一改成调用同一个连接对象。

2.4 目录权限与 Access 并发写锁

Access 在 IIS 下要求进程账户对数据库文件有写权限,否则执行update时报“不能更新。数据库或对象为只读”。建议按最小权限给:

  • 站点根目录:IUSRIIS_IUSRS只给“读取和执行”,防止用户改源码;
  • 数据库所在目录:单独给“写入”权限,Access 写库时会生成.ldb锁文件,写不进去会提示“文件正在使用”;
  • admin目录:关闭目录浏览,防止有人直接列源码文件。

到这里,访问http://localhost/baoxiu/index.asp如果正常显示,说明 ASP 解析没问题,接下来测报修提交即可。如果报错,优先看事件查看器,错误大多指向数据库路径或 Provider 注册。

3. 报修流程拆解:从index.asp到weixiu.asp的表单处理与状态流转

3.1 一个文件承担两个角色:显示表单和处理提交

index.asp通过<!--#include file="top.asp"-->引入公共头部,把登录入口、报修入口和最新状态放到一张页面上。用户点“我要报修”进入weixiu.asp,但真正有意思的是weixiu.asp内部根据Request("action")分流。

<% If Request("action") = "save" Then title = Trim(Request("title")) content = Trim(Request("content")) sql = "insert into repair(title, content, username, submit_time, status) values('" & title & "', '" & content & "', '" & Session("username") & "', Now(), 0)" conn.Execute sql Response.Redirect "index.asp?ok=1" Else %> <form method="post" action="weixiu.asp?action=save"> <input type="text" name="title" /> <textarea name="content"></textarea> <input type="submit" value="提交报修" /> </form> <% End If %>

这段代码里,action=save是判断条件,只有确实保存时才执行insert,否则就显示 HTML 表单。这样的好处是减少一个中间页面,坏处是 URL 参数直接决定了逻辑分支,扫代码时不容易一眼找到入口。Now()是 Access 的时间函数,status字段默认写 0,表示刚提交、未处理。Session("username")用来标记报修人,但如果用户没登录就访问这个页面,会写入空字符串,所以我在实际部署时会在文件开头加一行:

if Session("username") = "" then Response.Redirect "login.asp?from=weixiu"

同样,Request("title")Request("content")没有做长度限制,数据库表如果给字段定义了长度限制,超长内容会直接报错。可以在前端maxlength控制,但后端也要Len()判断一次。

3.2 维修单的状态流转:数字背后的意义

从后台校验代码推断,维修单表里有一个status字段,常见的映射关系是:

status含义
0待处理
1处理中
2已完成

admin/houtai.asp会优先列出status=0的记录,管理员点击处理时进入lyedit.asp,改状态并写处理内容。一般更新语句长下面这样:

<% id = CLng(Request("id")) newstatus = CInt(Request("status")) sql = "update repair set status = " & newstatus & ", handler = '" & Session("admin") & "' where id = " & id conn.Execute sql Response.Redirect "houtai.asp" %>

这里的CLngCInt是把输入参数按整数处理,能挡掉一部分不带数字的输入。但handler字段直接拼接了 session 里的管理员名,一旦 session 被伪造,会写进任意文本。所以我改成先对newstatus做白名单判断,只允许 0、1、2 三个值,不在范围内就跳回后台。

3.3 编辑、删除与防手滑

lyedit.asp的编辑逻辑复杂些,它先把维修单的原始内容select出来,显示在表单里,管理员填写处理意见后,再提交回去更新。dele_ly.asp则很简单,甚至有点危险:

<% id = Request("id") conn.Execute "delete from repair where id = " & id Response.Redirect "houtai.asp" %>

这段代码没做权限校验,也没做类型转换,任何人只要知道dele_ly.asp?id=3的格式,就能删任意记录。我改造时会加一个“确认删除”页面,或者至少判断来源页面是本机后台:

if InStr(LCase(Request.ServerVariables("HTTP_REFERER")), "houtai.asp") = 0 then Response.Write "非法操作" Response.End end if

HTTP_REFERER可以伪造,这只是防手滑,不是安全机制。真正要防,还得靠第 4 章讲的 session 校验。

3.4 按日期查询的经典写法

day.htm是一个静态页,里面放一个日期输入框,提交到part_star.asp,再用conn2.asp查询当天记录。Access 查询日期数据时,日期常量要用#包裹,不能像 SQL Server 那样用单引号:

<% d = Request("day") if IsDate(d) then sql = "select * from repair where submit_time >= #" & d & "# and submit_time < #" & DateAdd("d", 1, d) & "#" end if %>

IsDate先验证这是合法日期,避免非法字符串破坏 SQL;DateAdd("d", 1, d)取第二天的零点,这样能把某天 00:00:00 到 23:59:59 之间的所有记录都框进来。这种写法在 MySQL 里就得换DATE()函数,属于典型的 Access 迁移踩坑点。

4. 用户与权限:reg.asp注册、login.asp登录以及session鉴权的实现

4.1 注册页与新用户落地

reg.asp负责展示注册表单,regsubmit.asp接收表单参数并写用户表。为了防止机器人,系统用yanzheng.asp生成验证码,并把验证码字符存到 session:

' yanzheng.asp 片段 session("checkcode") = rndcode response.binarywrite ... ' 输出验证码图片

regsubmit.asp里比较用户输入和session("checkcode")。这里有个很隐蔽的问题:如果页面启用了缓存,或者用户打开注册页很久才提交,session 中的验证码可能已过期,导致反复提示“验证码错误”。我一般把这个 session 的过期时间设成 10 分钟,并在注册成功时立即清掉:

session("checkcode") = ""

另一个细节是注册表单提交的密码,老系统通常用自定义 MD5 函数加密,但要注意该函数返回的是 16 位还是 32 位 MD5。注册和登录两处用的必须是同一个函数,否则会出现注册成功但登录失败的诡异现象。

4.2 login.asp 登录验证与 session 初始化

登录页的逻辑并不复杂,查用户表,匹配则把用户名、用户 ID 写入 session,然后跳转首页。这段代码我在好几个系统里都见到过:

<% u = Trim(Request("username")) p = MD5(Trim(Request("password"))) sql = "select * from users where username = '" & u & "' and password = '" & p & "'" set rs = conn.Execute(sql) if not rs.eof then session("username") = rs("username") session("userid") = rs("id") response.redirect "index.asp" else response.redirect "login.asp?err=1" end if %>

注意MD5在这里是自定义函数,不是 VBScript 内置函数。很多老项目把 MD5 实现写在一个单独md5.asp里,如果页面没有 include 它就会报“缺少函数”。session("userid")用来在报修单上记录用户,比直接用字符串用户名更稳定,因为用户名可被注册页修改。

4.3 后台管理员鉴权:admin 目录的 session 检查

后台admin目录下每个页面都需要验证管理员身份,但 ASP 不会自动做这件事。标准做法是在后台公共头部 include 一个admin_check.asp,比如在houtai.asp最顶部:

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

admin_check.asp内容:

<% if session("admin") = "" then response.redirect "../login.asp?from=admin" end if %>

如果只是普通用户登录但没进后台,session("admin")为空,瞬间被弹回登录页。adduser.asp是管理员的用户管理页面,里面有新增用户、编辑用户权限的功能。这里需要警惕:如果这个页面没有做上面的 session 检查,任何知道路径的人都可以加一个管理员。这也是我拿到这套系统后第一个动手补的位置。

4.4 退出与超时:logout.asp 和 timeout.htm

logout.asp负责清 session,标准写法:

<% session.Contents.RemoveAll() session.Abandon() response.redirect "login.asp" %>

这里有个经验:如果只写session.Abandon(),在同一个响应周期内,某些旧 session 变量依然还能读出来,所以先RemoveAllAbandon更稳妥。timeout.htm是 session 超时后的提示页,IIS 默认 ASP session 超时是 20 分钟,可在应用程序池或global.asa里改更长。但这套系统没有global.asa,所以我只好在conn.asp里顺手设置了Session.Timeout = 30

5. 把老系统改到顺手:乱码、注入、分页三个关键改动

5.1 中文乱码:从页面编码到数据库排序

老系统在简体中文 Windows 上默认用 GBK,但现在的浏览器基本默认 UTF-8,不统一就会出现“鏂囦欢”这类乱码。第一步是给每个 ASP 页面顶部加上:

<%@ Language="VBScript" CodePage=65001 %> <% Response.CodePage = 65001 Response.Charset = "utf-8" %>

CodePage=65001让服务器把 ASP 内嵌的字符串按 UTF-8 发送,Response.Charset同时设置 HTTP 头里的字符集。如果数据库里的中文已经乱掉了,那要先把 Access 文本字段改成“文本”类型,并确认字段的 Unicode 压缩属性是“是”。Access 本身用 Unicode 存储文本,所以只要在写入前保证接收到的字节流是 UTF-8,乱码问题基本能压住。

5.2 参数化查询:别让 SQL 注入继续裸奔

第 3、4 章里出现的& Request("id") &拼接形式,在旧代码里到处都是。最廉价的改动是给所有取数字参数的位置都加上CLng,让非数字内容直接抛错。但真正的补法是重构成 ADO 参数化查询:

<% set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "select * from users where username = ? and password = ?" cmd.Parameters.Append cmd.CreateParameter("u", 200, 1, 50) cmd.Parameters.Append cmd.CreateParameter("p", 200, 1, 32) cmd.Parameters.Item(0).Value = u cmd.Parameters.Item(1).Value = p set rs = cmd.Execute %>

这里200adVarChar类型,1adParamInput5032是字段长度。?是 ADO Command 里的占位符,参数按顺序匹配。注意 Access 的 OLEDB 提供程序对?的解析有限制,如果一条 SQL 里有多个?,必须保证参数类型和顺序完全对应。改成参数化之后,用户名输入' or '1'='1只会被当成普通字符串,不会再破坏查询语义。

5.3 给维修单列表加分页

后台houtai.asp如果不分页,记录一多整个页面就卡死。加一个经典游标分页:

<% page = CInt(Request("page")) if page < 1 then page = 1 perpage = 15 sql = "select * from repair order by id desc" set rs = Server.CreateObject("ADODB.Recordset") rs.CursorLocation = 3 rs.Open sql, conn, 3, 1 rs.PageSize = perpage rs.AbsolutePage = page %>

CursorLocation=3adUseClient,客户端游标打开后才有AbsolutePage属性可用。rs.PageSize设置每页条数,rs.AbsolutePage直接跳到指定页。如果不用客户端游标,AbsolutePage会失效或报错。输出时用一个计数器控制序号,写完一页就自动断开。整个分页逻辑封装成子函数,比在每个页面上复制粘贴要省心。

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

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

10-03-高级-LINQ源码剖析-下-GroupBy-Join-Aggregate的底层原理

LINQ 源码剖析&#xff08;下&#xff09;&#xff1a;GroupBy、Join 与 Aggregate 系列&#xff1a;C# 与常用数据结构源码剖析 高级特性篇 阅读时间&#xff1a;约 80 分钟 源码基线&#xff1a;.NET 8.0.0&#xff0c;dotnet/runtime 的 System.Linq&#xff1a;Grouping.c…

作者头像 李华
网站建设 2026/9/12 19:17:05

Qt UDP接收完全指南:绑定、readyRead与文件分片重组

简介&#xff1a;这是面向Qt网络开发初学者的UDP通信示例项目&#xff0c;集中解决UDP消息收发、数据接收与文件分块传输三方面的实现问题&#xff0c;可直接用于理解QUdpSocket、QNetworkDatagram等核心类的典型用法。压缩包共17个文件、约814KB&#xff0c;包含3个C源文件、3…

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

从“淘票票.zip”看ZIP故障排查:EOCD、编码与现场数据提取

简介&#xff1a;这是一份名为“淘票票”的小程序项目源码&#xff0c;面向小程序开发学习者和票务类应用开发者&#xff0c;旨在通过完整工程示例展示小程序从页面搭建到业务逻辑实现的全过程。压缩包为zip格式&#xff0c;大小仅4.13MB&#xff0c;共包含40个文件&#xff0c…

作者头像 李华
网站建设 2026/9/12 19:15:40

从多维表格到六级权限:CRM商机管理选型指南

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

作者头像 李华
网站建设 2026/9/12 19:15:28

OMAP-L138启动引导实战:UBL镜像选型与AIS烧写全流程解析

简介&#xff1a;面向OMAP-L138嵌入式开发者的FlashAndBootUtils工具包&#xff0c;专为解决基于TI OMAP-L138&#xff08;集成Cortex-A8与C6000 DSP&#xff09;系统的固件烧写与引导启动问题&#xff0c;适用于U-Boot移植、NAND/NOR/SPI启动配置及量产烧录等场景。压缩包共71…

作者头像 李华
网站建设 2026/9/12 19:14:09

被动式太阳能遮阳系统设计与优化

1. 项目背景与核心挑战解析被动式太阳能遮阳系统是建筑节能领域的前沿研究方向&#xff0c;其核心在于不依赖主动能源输入的情况下&#xff0c;通过建筑本体设计实现夏季遮阳与冬季采光的动态平衡。2026年MCM美赛选择此题&#xff0c;反映了全球建筑行业对碳中和目标的迫切需求…

作者头像 李华