老式ASP+Access报修系统:部署、流程与安全改造实战
简介一款基于ASP的网页版报修系统面向企事业单位后勤、学校及物业等场景帮助管理员快速搭建线上报修平台让用户在线提交维修申请并跟踪处理进度。压缩包共52个文件整体仅793KB以ASP动态页面为主辅以JS交互脚本、CSS样式表、HTM页面和JPG/GIF图片素材另有IIS配置工具与使用说明解压后即可按文档部署调试。系统覆盖用户注册登录、报修单填写、后台管理、留言反馈等常用环节模块划分清晰适合有ASP基础的学习者参考其前后台实现思路描述中提到功能强大、易上手但也存在一些可优化之处因此也适合二次开发时对照改进。已有88人学习下载对想了解传统ASP报修系统结构或需要轻量级内网报修方案的用户是一份实用的入门资料。1. 报修系统baoxiu.rar一套仍在运行的ASPAccess报修台解压开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.js、date.js这类前端脚本。核心文件的作用先列出来方便后面对照文件角色说明conn.asp数据库连接几乎每个页面都会 include负责打开 Access 连接conn2.asp第二连接用于后台统计、按日期查询等独立数据链路index.asp前台首页展示报修入口、公告和维修状态weixiu.asp报修提交接收表单并写入维修记录login.asp登录校验用户密码写入 sessionreg.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就可以继续。如果缺失补装后重置 IISInstall-WindowsFeature Web-ASP iisreset这里Web-ASP指的是 IIS 的 ASP 功能角色不是某个第三方组件。装完后要把站点根目录的权限放开给IIS_IUSRS否则访问时会弹 500.19 或“无法识别该 URI 方案”。右键目录 - 安全 - 编辑给IIS_IUSRS至少“读取和执行”权限。2.3 conn.aspAccess 连接字符串的参数拆解这套系统里几乎所有页面顶部都会 include 一个conn.asp它负责创建 ADODB.Connection。老代码典型写法% Dim conn, db, connstr db data/baoxiu.mdb connstr ProviderMicrosoft.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时报“不能更新。数据库或对象为只读”。建议按最小权限给站点根目录IUSR和IIS_IUSRS只给“读取和执行”防止用户改源码数据库所在目录单独给“写入”权限Access 写库时会生成.ldb锁文件写不进去会提示“文件正在使用”admin目录关闭目录浏览防止有人直接列源码文件。到这里访问http://localhost/baoxiu/index.asp如果正常显示说明 ASP 解析没问题接下来测报修提交即可。如果报错优先看事件查看器错误大多指向数据库路径或 Provider 注册。3. 报修流程拆解从index.asp到weixiu.asp的表单处理与状态流转3.1 一个文件承担两个角色显示表单和处理提交index.asp通过!--#include filetop.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?ok1 Else % form methodpost actionweixiu.asp?actionsave input typetext nametitle / textarea namecontent/textarea input typesubmit value提交报修 / /form % End If %这段代码里actionsave是判断条件只有确实保存时才执行insert否则就显示 HTML 表单。这样的好处是减少一个中间页面坏处是 URL 参数直接决定了逻辑分支扫代码时不容易一眼找到入口。Now()是 Access 的时间函数status字段默认写 0表示刚提交、未处理。Session(username)用来标记报修人但如果用户没登录就访问这个页面会写入空字符串所以我在实际部署时会在文件开头加一行if Session(username) then Response.Redirect login.asp?fromweixiu同样Request(title)和Request(content)没有做长度限制数据库表如果给字段定义了长度限制超长内容会直接报错。可以在前端maxlength控制但后端也要Len()判断一次。3.2 维修单的状态流转数字背后的意义从后台校验代码推断维修单表里有一个status字段常见的映射关系是status含义0待处理1处理中2已完成admin/houtai.asp会优先列出status0的记录管理员点击处理时进入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 %这里的CLng和CInt是把输入参数按整数处理能挡掉一部分不带数字的输入。但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?id3的格式就能删任意记录。我改造时会加一个“确认删除”页面或者至少判断来源页面是本机后台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先验证这是合法日期避免非法字符串破坏 SQLDateAdd(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?err1 end if %注意MD5在这里是自定义函数不是 VBScript 内置函数。很多老项目把 MD5 实现写在一个单独md5.asp里如果页面没有 include 它就会报“缺少函数”。session(userid)用来在报修单上记录用户比直接用字符串用户名更稳定因为用户名可被注册页修改。4.3 后台管理员鉴权admin 目录的 session 检查后台admin目录下每个页面都需要验证管理员身份但 ASP 不会自动做这件事。标准做法是在后台公共头部 include 一个admin_check.asp比如在houtai.asp最顶部!--#include fileadmin_check.asp--admin_check.asp内容% if session(admin) then response.redirect ../login.asp?fromadmin end if %如果只是普通用户登录但没进后台session(admin)为空瞬间被弹回登录页。adduser.asp是管理员的用户管理页面里面有新增用户、编辑用户权限的功能。这里需要警惕如果这个页面没有做上面的 session 检查任何知道路径的人都可以加一个管理员。这也是我拿到这套系统后第一个动手补的位置。4.4 退出与超时logout.asp 和 timeout.htmlogout.asp负责清 session标准写法% session.Contents.RemoveAll() session.Abandon() response.redirect login.asp %这里有个经验如果只写session.Abandon()在同一个响应周期内某些旧 session 变量依然还能读出来所以先RemoveAll再Abandon更稳妥。timeout.htm是 session 超时后的提示页IIS 默认 ASP session 超时是 20 分钟可在应用程序池或global.asa里改更长。但这套系统没有global.asa所以我只好在conn.asp里顺手设置了Session.Timeout 30。5. 把老系统改到顺手乱码、注入、分页三个关键改动5.1 中文乱码从页面编码到数据库排序老系统在简体中文 Windows 上默认用 GBK但现在的浏览器基本默认 UTF-8不统一就会出现“鏂囦欢”这类乱码。第一步是给每个 ASP 页面顶部加上% LanguageVBScript CodePage65001 % % Response.CodePage 65001 Response.Charset utf-8 %CodePage65001让服务器把 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 %这里200是adVarChar类型1是adParamInput50和32是字段长度。?是 ADO Command 里的占位符参数按顺序匹配。注意 Access 的 OLEDB 提供程序对?的解析有限制如果一条 SQL 里有多个?必须保证参数类型和顺序完全对应。改成参数化之后用户名输入 or 11只会被当成普通字符串不会再破坏查询语义。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 %CursorLocation3是adUseClient客户端游标打开后才有AbsolutePage属性可用。rs.PageSize设置每页条数rs.AbsolutePage直接跳到指定页。如果不用客户端游标AbsolutePage会失效或报错。输出时用一个计数器控制序号写完一页就自动断开。整个分页逻辑封装成子函数比在每个页面上复制粘贴要省心。本文还有配套的精品资源点击获取