十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ASP药店管理系统源码解析:从IIS部署到SQL注入防御

ASP药店管理系统源码解析:从IIS部署到SQL注入防御 简介面向ASP课程设计与毕业设计的药店管理系统完整项目资料包适合计算机相关专业学生在课题设计、模块拆分与论文撰写时参考。压缩包共一百三十三个文件大小约5.23MB主体为82个asp动态页面文件配合css样式表与jpg/gif界面截图展示页面效果另含12个doc文档、2个ppt答辩演示文稿及SQL Server数据库文件mdf/ldf集源码、论文、开题报告与答辩幻灯片于一体。系统实现了商品信息增删改查、库存自动增减、销售明细记录、客户档案与分级管理员权限等典型业务并针对SQL注入、XSS攻击做了基础安全设计。这些内容既可作为ASP连接数据库的入门练手也能直接改写成课程设计或毕业设计成果。目前已有406人学习下载适合需要完整参考项目或快速搭建系统原型的开发者。1. 药店管理系统的 ASP 技术选型与毕业设计场景这套 ASP 药店管理系统源代码之所以在毕业设计里一直有市场不是因为 ASP 技术本身有多先进而是它把库存管理、销售记录、客户档案、管理员权限这些业务模块压缩在一个不到十个页面的 B/S 应用里正好覆盖课程设计和论文答辩需要的全部知识点。包里除了源码还带了论文、开题报告和答辩 PPT这意味着你可以把精力花在“看懂代码、讲清设计”上而不是从零搭框架。项目正文里那几个文件——adovbs.asp、md5.asp、mededit.asp、medadd.asp、left.asp——就是系统的技术骨架分别对应数据库访问层、加密算法层和业务表单层。对要做 ASP 毕业设计的人来说这份资源的价值在于它是一套可以完整复现的旧式 Web 应用样本对维护过老系统的工程师来说它同样适合用来补一轮 ASP 语法和 ADO 对象模型的课。2. 运行环境重建Win11 下 IIS 与 ASP 配置2.1 为什么 IIS 是唯一推荐运行时ASP 是微软的服务器端脚本环境官方运行时就是 IIS这一点决定了它在非 Windows 平台上的兼容性非常差。Apache 上虽然挂着 mod_aspdotnet 之类的第三方模块但报错信息混乱跑老代码经常出现函数未定义、Session 行为不一致的问题。我一般拿到这种老项目第一件事不是在 IDE 里打开 ASP 文件而是先把 IIS 跑通让最简单的 ASP 页面能输出内容再逐步引入数据库连接。Win11 的 IIS 默认不安装需要在“启用或关闭 Windows 功能”里手动勾选也可以通过命令行一次性装好。这个步骤对新手是第一个拦路虎因为 IIS 功能列表里有十几个子项少勾一个就会出现 ASP 页面无法解析的情况。在 Win11 上配置 IIS ASP 时最核心的其实是“默认文档顺序”和“应用池 32 位设置”这两处它们决定了你访问 index.asp 时能否正常渲染。2.2 启用 IIS 和 ASP 的两种方式第一种是图形界面控制面板 → 程序 → 启用或关闭 Windows 功能 → 勾选 Internet Information Services再展开“应用程序开发功能”把 ASP 勾上。第二种是命令行管理员权限下执行dism.exe /Online /Enable-Feature /FeatureName:IIS-WebServerRole /all dism.exe /Online /Enable-Feature /FeatureName:IIS-ASP /all iisreset /restart第一条命令里/Online表示操作当前运行中的系统镜像/FeatureName指定要启用的功能名称/all表示把依赖的子功能一并启用。iisreset /restart的作用是重启 IIS 服务让配置立即生效。这套命令适合直接用脚本部署服务器或批量初始化测试机的场景。2.3 站点与应用池配置创建网站时物理路径直接指向解压目录。需要注意两点路径里不要带中文空格否则Server.MapPath返回的路径容易出现编码错乱站点目录要给IIS_IUSRS用户添加“读取和执行”权限否则会报 500.19。应用池建议选择“经典”托管管道模式并开启“启用 32 位应用程序”因为 Access 数据库的 Jet OLEDB 驱动只有 32 位版本。现象常见原因处理方式HTTP 404.3ASP 脚本映射丢失重新勾选 IIS 的 ASP 功能或修复安装HTTP 500.19目录权限或配置文件错误给目录添加 IIS_IUSRS 读取权限ASP 0126包含文件路径写错检查#include file目标文件是否存在0x80004005Jet 驱动不可用安装 AccessDatabaseEngine 并开启 32 位应用池上面这张表覆盖了配置阶段绝大部分报错。第一次遇到 404.3 时很多人会以为是文件缺失其实是 IIS 的 ASP 模块没有注册完毕重跑一次dism命令即可。0x80004005 则是最典型的数据库连接失败后面第三章会展开讲。2.4 验证 ASP 是否可执行在站点根目录新建一个 test.asp 文件% Response.Write ASP is running. Time: Now() %Now()是 VBScript 的时间函数返回服务器当前时间。浏览器访问http://localhost/test.asp如果页面输出时间文本说明 ASP 解析正常。这里有个细节如果浏览器直接弹下载框或显示源码说明 IIS 没把 .asp 交给 ASP 模块处理不是页面问题而是功能没装全。3. 数据库设计Access 表结构、ADO 连接与库存扣减3.1 表结构拆解药店管理系统虽然业务简单但表结构设计上仍然遵守“主表 明细表”的经典模式。核心表包括管理员表、药品表、销售主表、销售明细表和客户表。其中药品表是最常被查询的销售主表和明细表分开的目的是为了统计订单总金额时只扫主表而明细表里保存了当时成交单价避免日后药品调价导致历史报表对不上。以药品表为例典型字段如下字段名类型说明MedicineID自动编号主键DrugName文本药品名称Specification文本规格如 5mg×10片UnitPrice货币售价StockQty整型当前库存数量ExpiryDate日期/时间有效期Supplier文本供应商名称这套字段能在实际业务里支撑“库存预警”和“临期提醒”两个功能。写 SQL 时库存预警用WHERE StockQty AlertNum临期提醒用WHERE ExpiryDate BETWEEN Date() AND DateAdd(d, 90, Date())这两个查询在答辩演示时很容易出效果。3.2 ADO 连接串与三种连接方式数据库连接是整套代码的枢纽。ASP 访问 Access 数据库一般使用 ADODB.Connection 对象连接串如下% Dim conn Set conn Server.CreateObject(ADODB.Connection) conn.ConnectionString ProviderMicrosoft.Jet.OLEDB.4.0;Data Source Server.MapPath(data/medicine.mdb) conn.Open %Server.MapPath用于把站点虚拟路径映射为服务器物理路径这里传的参数data/medicine.mdb是相对于站点根目录的。Provider指定 OLE DB 提供程序Jet.OLEDB.4.0 适用于 Access 2003 及更早的 mdb 文件如果换成 accdb 后缀必须把 Provider 改成Microsoft.ACE.OLEDB.12.0。很多老项目报 0x80004005 就是因为连接串写的是 mdb 路径但实际数据库文件已经被人用 Access 2016 另存成了 accdb。连接时有个隐藏细节Access 数据库文件若放在站点目录内且没有设置读取权限IIS 可能直接把文件当作静态资源供下载。后面安全章节会专门讲。3.3 库存扣减的 SQL 写法与超卖问题销售药品时最关键的 SQL 不是 INSERT 销售记录而是库存扣减。常见的错误写法是先 SELECT 查库存再用 UPDATE 扣数这种两步操作在高并发下会超卖。单机库存扣减更稳的方式是条件更新UPDATE Medicine SET StockQty StockQty - 2 WHERE MedicineID 101 AND StockQty 2这条语句把“库存是否充足”的判断合并进 UPDATE影响行数为 1 表示扣减成功影响行数为 0 说明库存不足业务层据此拒绝下单。在 ADO 里判断影响行数可以用conn.Execute(sql, rowsAffected)第二参数接收受影响行数。配合事务可以保证销售主表、明细表、库存表三处写入要么全部成功要么全部回滚。conn.BeginTrans conn.Execute INSERT INTO Sales(CustomerID, SalesDate, TotalAmount) VALUES(1, Now(), 55) conn.Execute INSERT INTO SalesDetail(SalesID, MedicineID, Quantity, Price) VALUES(1, 101, 2, 27.5) conn.Execute UPDATE Medicine SET StockQty StockQty - 2 WHERE MedicineID 101 AND StockQty 2 conn.CommitTransBeginTrans开启事务CommitTrans提交事务中间任何语句出错就执行RollbackTrans撤销前面所有操作。注意 Access 不支持行级锁定事务粒度要尽量小不要在事务里做耗时的查询。4. 核心源代码走查adovbs.asp、md5.asp 与 mededit.asp4.1 adovbs.aspADO 常量统一引用的意义adovbs.asp 本质上是微软官方提供的 VBScript 常量定义文件它把 ADO 里大量的数字常量用有意义的名称替换掉。文件内容并不复杂全是类似Const adOpenForwardOnly 0这样的声明但少了它代码里就会出现大量裸数字可读性极差。实际编写 ADO 记录集代码时逻辑是这样的!--#include fileadovbs.asp-- % Dim rs Set rs Server.CreateObject(ADODB.Recordset) rs.Open sqlText, conn, adOpenKeyset, adLockOptimistic, adCmdText %adOpenKeyset表示键集游标值为 1允许在记录集中看到其他用户修改的数据adLockOptimistic表示乐观锁定值为 3只在调用 Update 时才锁定记录adCmdText表示第一个参数是 SQL 文本而非表名值为 1。如果不 include 这个文件代码会直接报“变量未定义”。4.2 md5.aspVBScript 加密实现与编码坑md5.asp 是一个纯 VBScript 编写的 MD5 算法实现不需要额外组件。在登录模块里的典型调用方式如下% If MD5(Request.Form(password)) rs(Pwd) Then Session(AdminID) rs(AdminID) End If %MD5 函数接收字符串返回 32 位十六进制哈希值。但直接这样用在中文密码或混合编码场景下非常容易踩坑因为 ASP 页面默认的字符串编码是 ANSI而某些老数据库里的哈希是基于 UTF-8 字节序列计算的两边一旦不一致登录永远失败。稳妥做法是用 ADODB.Stream 做一次编码转换Function MD5Utf8(s) Dim stream Set stream Server.CreateObject(ADODB.Stream) stream.Type 2 stream.Charset utf-8 stream.Open stream.WriteText s stream.Position 0 MD5Utf8 MD5(stream.ReadText) stream.Close End FunctionType 2表示文本流Charset utf-8指定字符集WriteText写入原始字符串ReadText读取转换后的文本。这个过程相当于把字符串在内存里做了一次编码校准两个系统的哈希基准就统一了。4.3 mededit.asp药品编辑页面的典型流程mededit.asp 是药品管理的编辑页面它的请求处理方式是理解整个系统的关键。这个文件里同时存在两个角色展示模式和保存模式通过请求参数区分。% cmd Request(cmd) If cmd save Then id Request(id) name Request(name) price Request(price) conn.Execute UPDATE Medicine SET DrugName name , UnitPrice price WHERE MedicineID id Response.Redirect mededit.asp?id id End If %Request(cmd)会同时从查询字符串和表单取值因此一个页面既能通过mededit.asp?id101进入编辑态也能通过表单提交cmdsave进入保存逻辑。Response.Redirect返回列表页时一定要在后一行加Response.End否则重定向之后代码还会继续执行可能输出多余内容导致页面错乱。这段代码里最明显的问题是 SQL 字符串拼接。name和price直接嵌入 SQL如果药品名称里包含单引号就会语法报错如果被构造出; DROP TABLE ...这类输入后果更严重下一章专门处理这个。5. 登录、权限与注入防御ASP 安全的边界在哪里5.1 Session 登录校验的正确打开方式ASP 的登录状态通常存在 Session 对象里Session 是服务端变量按会话隔离比 Cookie 更安全。后台每个页面顶部几乎都有同样一段代码% If Session(AdminID) Then Response.Redirect login.asp Response.End End If %判断逻辑很简单但很多人漏写Response.End导致重定向未生效残留的 HTML 和脚本继续输出给浏览器。更隐蔽的问题是 Session 超时后Ajax 请求不会自动跳转登录页处理时需要对返回状态做出 JSON 结构化约定这已经属于后续改造范畴老系统一般不管。5.2 SQL 注入定位与修复登录模块是 SQL 注入的重灾区典型漏洞代码长这样SELECT * FROM Admin WHERE UserName Request.Form(username) AND Pwd Request.Form(password) 在用户名输入框里填 OR 11拼接后的 SQL 变成SELECT * FROM Admin WHERE UserName OR 11 AND Pwd由于OR 11恒为真整条查询返回 Admin 表全部记录第一条记录就是管理员登录被直接绕过。更稳妥的修复方案是参数化查询把用户输入作为参数而不是 SQL 文本Dim cmd, paramUser, paramPwd Set cmd Server.CreateObject(ADODB.Command) cmd.ActiveConnection conn cmd.CommandText SELECT * FROM Admin WHERE UserName? AND Pwd? cmd.CommandType adCmdText Set paramUser cmd.CreateParameter(u, 200, 1, 50, userName) cmd.Parameters.Append paramUser Set paramPwd cmd.CreateParameter(p, 200, 1, 50, pwd) cmd.Parameters.Append paramPwd Set rs cmd.ExecuteCreateParameter的第一个参数是参数名仅做标识第二参数 200 是adVarChar表示可变长字符串第三参数 1 是adParamInput表示输入型参数第四参数 50 是最大长度第五参数是运行时实际值。参数化之后用户输入中的单引号会被当作字符串内容处理不再具备闭合 SQL 的能力。老项目如果改造成本高最低限度也要把单引号转义成两个单引号Replace(str, , )但这只堵住了常规注入并没有根治问题。5.3 分级权限与后端校验这套系统的管理员不应只有一档建议在 Admin 表加 Role 字段1 代表普通店员2 代表店长3 代表系统管理员。权限判断放在后端If Session(Role) 2 Then 执行药品信息修改 Else Response.Write 无权限 Response.End End IfRole在登录成功后写入 Session每次操作前重新校验。前端隐藏按钮只是交互优化真正的权限控制必须发生在服务器端这一点答辩时经常被追问。5.4 密码存储与数据库文件保护密码绝不能明文存储md5.asp 已经提供了哈希能力但只做一次 MD5 容易被彩虹表命中加盐是对抗手段pwdHash MD5(password | userName)盐值选用与用户相关的信息|作为分隔符防止拼接歧义。即使两个用户密码相同哈希结果也不同。Access 数据库文件本身也要做保护把它移到站点根目录之外或者给文件加只读权限并禁止匿名下载。安全项推荐做法登录密码MD5 加盐哈希存储数据库文件放在站点物理目录之外SQL 拼接登录、修改处改用参数化查询会话控制每页校验 Session 并调用 Response.End权限控制后端按 Role 字段判断不依赖前端隐藏6. 调试与收尾老 ASP 项目最常见的三个验证点6.1 关闭浏览器友好错误信息ASP 报错时IE 和 Edge 默认显示“HTTP 500 - 服务器错误”这类友好页面真实错误被吞掉。调试前先把浏览器设置里的“显示友好 HTTP 错误信息”关掉重新访问出错页面就能看到Microsoft VBScript 运行时错误和具体的行号。IIS 侧也要在“错误页”功能里把响应模式改为“详细错误”这样本机调试时能直接看到源码定位。6.2 用 F12 观察 302 跳转和 Session 失效登录失效类问题很容易从开发者工具的 Network 面板看出来。访问后台页面时如果第一个请求返回 302Location 指向 login.asp说明 Session 已过期或未被写入。然后切到 Application 面板查看 Cookie确认会话标识是否存在。我调试这类系统时习惯在登录成功的代码里加一句Response.Write Session(AdminID)确认会话值确实写进去了再移除调试输出。6.3 压缩修复 Access 数据库Access 数据库在长期增删改后会产生碎片体积膨胀查询变慢。用 Access 客户端打开 mdb 文件执行“工具 → 压缩和修复数据库”即可。如果无法打开可能是站点目录下有同名.ldb锁文件说明数据库正被 IIS 占用先停掉对应应用池再操作。日常备份不用停站直接复制 mdb 文件到目标目录但要注意复制期间可能有人写入最保险的做法是在凌晨低峰期备份。最后用Response.Write输出关键变量的值是 ASP 时代最高效的调试手段之一比查日志直接得多。定位到问题点后记得把临时输出的调试文本全部注释掉否则页面源代码里会留着测试痕迹。本文还有配套的精品资源点击获取
返回列表