基于经典ASP的GM推广系统v6.0部署与安全实践
简介面向游戏管理员与ASP开发者的GM专用游戏推广系统v6.0完整源码包基于经典ASP技术构建适用于游戏推广活动管理与后台搭建。无论是独立游戏工作室还是运营中的网络游戏均可直接部署使用。系统集成用户管理、推广链接追踪、数据统计、广告投放、奖励机制、API对接及安全防护等核心模块GM可借此高效管理玩家账户、评估渠道效果并精准推送广告开发者也能从具体代码中学习服务端动态网页、权限控制、数据库交互等经典实现思路。包内共490个文件含205个gif图片、140个PHP脚本、52个JS脚本、27个PNG图片、23个HTML页面、17个CSS样式等另附TXT说明与DLL组件整体仅1.77MB目录结构清晰便于按模块检索与二次开发。已有148人浏览学习适合具备一定ASP基础、希望快速搭建推广后台或研究经典Web服务端架构的人群。1. GM 要推广游戏ASP 源码为什么还能打GM 要推广游戏不止发公告。GM 要在各个渠道挂推广链接、给渠道玩家发标记、批量生成激活码和礼包码、核对渠道转化数据再通过游戏侧的 GM 命令把奖励落到玩家角色上。把这些流程收拢到一个后台里就是一个独立的推广系统而标题里这个 v6.0 zip 用的技术栈是经典 ASP.asp 页面加数据库脚本加说明文档的一整套源码。相比 Python/Go 方案经典 ASP 的最大优势是部署只依赖 IIS没有额外运行时代码解释执行、文件即逻辑改几行字符串就能在 Windows 服务器上跑起来。适合还在维护 ASP 项目的游戏运营团队也适合想把老 GM 后台迁到新版 Win11 环境的人。下面按“解压阅读 → IIS 部署 → 核心功能 → 安全加固 → 冒烟测试”的顺序拆开讲。2. 解压后先读文件结构ASP 项目的三条基础链路经典 ASP 项目没有编译步骤IIS 直接把 .asp 文件当脚本执行所以文件结构就是系统结构。拿到 zip我建议先做一次文件体检把页面、数据库、配置文件一屏列出来这比看任何说明文档都直观mkdir -p /workspace/gsv6 unzip -q ASP源码—GM专用游戏推广系统 v6.0.zip -d /workspace/gsv6 cd /workspace/gsv6 find . -maxdepth 3 -type f \( -name *.asp -o -name *.mdb -o -name *.accdb -o -name *.sql \) | sort | head -60第一段命令把 zip 解压到独立目录第二段筛出 ASP 页面和两类数据库文件。head -60是为了避免页面太多刷屏。看到 install.asp 或 upgrade.asp 时优先访问它完成安装向导看到 admin/ 和 api/ 两个平级目录基本可以判断这是“后台管理 对外接口”的结构。下面这张表记录了我拿到包之后会重点核对的位置路径示例在 GM 推广系统里的职责我会重点看什么admin/login.aspGM 后台登录页登录字段名和密码处理方式inc/conn.asp数据库连接串Provider、数据库类型inc/auth.asp登录态与角色校验是否每个后台页面都引用api/gm_hook.asp游戏服务器回调入口有没有 Token 或签名校验db/gm_db.accdb业务数据表名、激活码表、渠道表uploads/推广图、活动页素材是否禁止执行脚本在经典 ASP 项目里目录命名高度一致inc 放公共函数admin 放管理页uploads 或 upload 放上传文件backup 或 db 放数据库。把这六个位置扫完一个 GM 推广系统的边界就清楚了。2.1 从 conn.asp 到 index.asp一次完整请求的执行顺序浏览器请求 index.asp 时IIS 的 ASP 引擎从上到下解释执行页面脚本与 HTML 混排遇到 ADODB 对象就操作数据库。最常见的首页逻辑是先 include 公共连接文件再判断 Session 登录态然后查表渲染页面。下面是最典型的一套写法% 登录态检查gm_id 为空跳回登录页 If Session(gm_id) Then Response.Redirect admin/login.asp Response.End End If % !--#include fileinc/conn.asp --Response.End在这里不是可选项。Response.Redirect 只是向浏览器发送 302 跳转指令后面的代码仍然会继续执行不写 End未登录用户虽然看到了登录页但数据库查询和页面输出仍然跑了一遍。在 GM 系统里这等于给未授权请求保留了信息回显路径。include 语句放在登录检查之后既避免每个页面重复写连接代码也方便统一改连接串。2.2 Access 还是 SQL Server连接字符串是第一个分水岭解压后如果看到 .mdb 或 .accdb说明系统默认使用 Access如果附带 .sql 脚本说明支持迁移到 SQL Server。GM 推广系统的真实场景是后台同时登录多个 GM各自生成激活码、查渠道、发奖励Access 在几个并发连接内还能应付一旦超过十几个连接写卡和查流水会互相锁死。所以我会先确认默认数据源再决定部署策略。 本机 Access 数据库.accdb 需要安装 Access Database Engine connStr ProviderMicrosoft.ACE.OLEDB.12.0;Data Source Server.MapPath(db/gm_db.accdb) 远程 SQL Server适合多人协作部署 connStr ProviderSQLOLEDB;Server192.168.1.10,1433;DatabaseGMDB;Uidgmapp;Pwdxxx Set conn Server.CreateObject(ADODB.Connection) conn.Open connStr连接串里最常改的是 Provider 和 Data Source。ACE.OLEDB.12.0 是 Access 2007 以后的标准驱动读取 .mdb 和 .accdb 都可以如果系统老到还用 Jet.OLEDB.4.0就只能在 32 位应用池下跑这一点直接决定了 3.2 小节的设置。SQLOLEDB 是经典 ASP 连 SQL Server 的老牌写法新环境可以用 SQLNCLI11但改动小、测试少的话先保持 SQLOLEDB 更稳。Data Source 里的,1433是端口实例名则用Server主机名\实例名的格式两种写法只能选一种。2.3 除了 conn.asp还要搜一遍所有连接串GM 系统往往不止一个连接配置。后台页面、接口文件、计划任务脚本可能各自维护一份连接串改漏一个就会出现“登录正常发卡报错”的诡异现象。我一般会在项目根目录执行grep -rn Provider --include*.asp .把每个 Provider 和 Data Source 都列出来统一改成同一目标库。这里还要注意Access 模式下连接串里写的是相对路径SQL Server 模式下是网络地址两种模式混在一个项目里会导致部分页面连本机文件、部分页面连远程库排查起来非常痛苦。3. 跑起来Win11 配置 IIS 跑 ASP 的部署四步经典 ASP 在 Win11 上不是装上 IIS 就能跑IIS 默认不启用 ASP 角色。这个坑在实际部署中碰到概率接近百分之百。下面四个步骤分别处理启用功能、修正运行参数、改连接串、查启动错误。3.1 用 PowerShell 打开 IIS 与 ASP 角色打开管理员 PowerShell执行Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerRole, IIS-ASP -All Restart-Computer这段命令的作用是让系统补上 IIS 主服务和经典 ASP 的 ASP 引擎。-Online表示操作当前系统IIS-WebServerRole是 IIS 的总开关IIS-ASP是经典 ASP 的独立组件缺了它 .asp 文件会被当成纯文本下载或者直接返回 404.3-All让依赖项一并启用。重启是必要的IIS 的角色变更经常要等系统服务重启后才会完全生效。重启后执行下面的命令确认Get-WindowsOptionalFeature -Online -FeatureName IIS-ASP | Select-Object FeatureName, StateState 是 Enabled 就说明 ASP 引擎可用。如果这里是 Disabled先重启一次再查仍然不行就检查系统镜像版本家庭版和专业版的可选功能列表有差异。3.2 两个默认值必改父路径和 32 位应用池功能启用后大部分 .asp 网站启动失败都出在两个默认值上。第一是“启用父路径”。经典 ASP 默认不允许在 Server.MapPath 里使用../而老源码为了方便经常会写Server.MapPath(../upload/)。打开 IIS 管理器选中网站双击 ASP 图标在“行为”分组里把“启用父路径”设为 True或用 appcmd 直接改C:\Windows\System32\inetsrv\appcmd.exe set config Default Web Site /section:asp /enableParentPaths:true /commit:apphostenableParentPaths:true对应管理器里的开关/commit:apphost把设置写进 applicationHost.config这样不会因为站点级配置冲突而失败。第二是 32 位应用池。如果 inc/conn.asp 里用的是 Jet.OLEDB.4.064 位 IIS 应用池会报“未在本地计算机上注册”的错误。解决方法是到“应用程序池”里选中对应池右键高级设置把“启用 32 位应用程序”设为 True。使用 ACE.OLEDB.12.0 则不需要这一步可保持 False。3.3 连接字符串三种场景的改法部署时首先要改的就是连接字符串。本机调试、服务器 Access、SQL Server 三种典型写法总结如下场景Provider注意点本机 .mdbMicrosoft.Jet.OLEDB.4.0应用池必须开启 32 位本机 .accdbMicrosoft.ACE.OLEDB.12.0需安装 AccessDatabaseEngine远程 SQL ServerSQLOLEDB 或 SQLNCLI11Uid/Pwd 鉴权注意特殊字符转义 本地调试Access 文件 connStr ProviderMicrosoft.ACE.OLEDB.12.0;Data Source Server.MapPath(db/gm_db.accdb) 远程数据库 connStr ProviderSQLOLEDB;Server192.168.31.20;DatabaseGMDB;Uidgmapp;Pwd123456!;注意 SQLOLEDB 的 Pwd 里如果包含特殊字符连接串会把分号误认为分隔符导致密码被截断。解决办法是把特殊字符换成对应转义或者直接避免在密码里用分号和引号。项目里如果同时在多个连接文件改完记得全局搜索连接字符串漏一个会让页面一半正常一半报错。3.4 500 错误先从事件日志和 ASP 调试属性查起启动后最常见的状态是“500.0 - Internal Server Error”。经典 ASP 的细节错误默认被吞掉页面只给一行笼统提示。打开 IIS 管理器选中网站双击 ASP在“调试属性”里把“向客户端发送错误”临时设为 True刷新页面就能看到包含“Microsoft VBScript runtime error”和行号的具体报错。看清问题代码之后再把这项改回 False避免把内部路径暴露给玩家。查不到时直接看系统事件日志Get-WinEvent -FilterHashtable {LogNameApplication; Level2; StartTime(Get-Date).AddHours(-1)} -MaxEvents 30 | Where-Object { $_.Message -match asp|w3wp|IIS } | Select-Object TimeCreated, Message | Format-ListLevel2 是错误级别消息里带 w3wp 表示工作进程崩溃带 ASP_ 前缀通常是脚本引擎错误。这两个方向定位完500 基本都能收敛到具体代码行或数据库驱动上。4. 把 GM 推广功能拆开激活码、推广链接、素材上传、GM 命令对接GM 专用推广系统的业务模块绕不开激活码、推广归因、素材上传和游戏侧发奖。这一章按功能切片每一片都给出能直接落到 ASP 页面里的实现方式。4.1 激活码生成去掉混淆字符先查重再入库激活码要给玩家手动录入字符集必须去掉 1、I、0、O 这四种容易看错的字符。下面是一个适合 GM 后台批量生成的最小函数Function GenCode(pLen) Dim i, idx, charSet charSet 23456789ABCDEFGHJKLMNPQRSTUVWXYZ Randomize For i 1 To pLen idx Int(Rnd * Len(charSet)) 1 GenCode GenCode Mid(charSet, idx, 1) Next End Function code GenCode(16) Set rs conn.Execute(SELECT COUNT(*) FROM t_cdkey WHERE code code ) If rs(0) 0 Then conn.Execute INSERT INTO t_cdkey(code, gm_id, channel, status, create_time) VALUES( code , Session(gm_id) ,web,0, Now() ) End IfpLen 传 16 是折中6 位太短、32 位玩家录入困难。Randomize 每次重置随机种子配合 Rnd 取 0 到 1 之间的小数乘上字符集长度后取整数再加一位得到的就是目标位字符。入库前先 COUNT 查重重了就重新生成。这里的 SQL 是演示拼接写法第 5 章我会给它换成参数化版本。GM 系统如果要大批量发卡可以把生成逻辑放进循环一次生成 500 条后统一提交事务速度远快于逐条 INSERT。4.2 推广链接跟踪用 QueryString 写 Cookie让第一次访问带上来源渠道推广链接通常长这样http://gm.example.com/reg.asp?fromkuaishou01。玩家点进来推广归因要把 from 的值记住之后 30 天内他注册GM 后台都能看到来源渠道。写法是在落地页顶部做一次定向% Dim refCode refCode Trim(Request.QueryString(from) ) If refCode Then Response.Cookies(gm_ref) refCode Response.Cookies(gm_ref).Expires DateAdd(d, 30, Now()) Response.Redirect reg.asp End If %Request.QueryString 取 URL 里的 from 参数Response.Cookies 写入浏览器Expires 设置为 30 天。注意Request.QueryString(from) 这种写法QueryString 缺参时返回 Empty拼接空字符串后 Trim 不会报错这是经典 ASP 里处理可选参数的标准套路。Redirect 到 reg.asp 是因为后续注册页面只需要读 Cookie不需要在地址栏二次携带渠道号。GM 后台统计时要按 Cookie 归因而不是按注册时的 from 参数归因防止玩家手动改链接刷渠道奖励。4.3 ASP 图片上传的目录与文件约束不能把上传目录当图床GM 推广要传活动 banner、游戏截图经典 ASP 上传通常靠无组件上传类或第三方组件。下面是校验文件和重命名的最小片段suffix LCase(Mid(targetName, InStrRev(targetName, .) 1)) If InStr(,jpg,jpeg,gif,png,webp,, , suffix ,) 0 Then Response.Write 文件类型不允许 Response.End End If newName Year(Now) Right(0 Month(Now), 2) Right(0 Day(Now), 2) _ Int(Rnd * 100000) . suffix SaveFile Server.MapPath(uploads/ newName)suffix 提取时切成小写InStrRev 从右侧找最后一个点避免文件名里带多个点导致取错后缀白名单用“逗号 值 逗号”的方式包住是为了匹配时不会把 jpg 误命中成 jpgg。newName 用日期加随机数构造替换掉用户原文件名。这里的 SaveFile 是上传组件提供的方法不同的无组件上传类方法名不一样你手头包里如果自带 upload.inc 或 upload_*.asp以包内函数为准。这样即使上传接口有漏洞攻击者也得先猜出随机文件名才能访问和 5.1 小节的目录权限设置配合能挡掉大部分风险。4.4 与游戏服务器的 GM 命令对接点只发指令不回执推广系统的终点是给玩家发奖励。常见做法不是让 Web 后台直连游戏数据库改角色物品而是把发奖请求推到游戏侧的管理接口由游戏服务器执行 GM 命令。简化的 ASP 调用代码Set http Server.CreateObject(MSXML2.ServerXMLHTTP) http.open POST, http://10.10.0.5:8088/gm, False http.setRequestHeader Content-Type, application/x-www-form-urlencoded http.send token Server.URLEncode(gmToken) cmdgrantrole Server.URLEncode(roleName) item1024num1 If http.status 200 And InStr(http.responseText, OK) 0 Then Response.Write 发放成功 Else Response.Write HTTP http.status http.responseText End Iftoken 是两边的共享密钥cmdgrant 表示发物role 是游戏角色名item 是物品 IDnum 是数量。同步调用 False 方式简单但游戏服处理慢时会阻塞 IIS 工作线程所以量大了要改成异步或者转成待发送队列表 t_gm_cmd由游戏服拉取。GM 命令的粒度要由游戏侧决定别在 Web 端拼接任意脚本字段交给游戏服防止有人把命令改成改角色等级甚至调用系统权限。5. 上线前把安全项过一遍上传、SQL 注入、后台越权GM 系统的权限比普通官网高一个量级安全上不能只依赖 IIS 默认配置。这里挑三个真实的失陷路径和一个底线要求展开。5.1 上传目录执行权限让 uploads 只存不跑经典 ASP 的坑在于 .asp 文件与 .jpg 文件可以同目录混跑。如果攻击者绕过 4.3 小节的扩展名校验传了一个 .asp 文件上去IIS 会把它当服务器脚本执行直接拿到运行权限。所以我一般会对 uploads 目录做两个操作IIS 管理器里选中该目录打开“处理程序映射”-“编辑功能权限”取消“脚本”勾选再把 uploads 目录归属的应用池与网站主池分开降低跨目录风险。操作完用下面命令验证Invoke-WebRequest http://127.0.0.1/uploads/test.asp -UseBasicParsing | Select-Object StatusCode如果返回 404.7 或 403.2说明脚本已被禁止执行如果返回 200 并输出内容说明上传防护失守。文件名随机化和目录只读权限能进一步压缩风险。5.2 不拼 SQL用 ADODB.Command 参数化替换所有字符串拼接GM 后台的查询类、删除类操作最容易被人利用 SQL 注入。4.1 小节的激活码查询如果用了拼接任何带单引号的输入都能夹带 SQL 语句。改造方向很统一全部改成 ADODB.Command。下面是一个可复用的查询片段Set cmd Server.CreateObject(ADODB.Command) Set cmd.ActiveConnection conn cmd.CommandType 1 adCmdText cmd.CommandText SELECT code FROM t_cdkey WHERE code? AND status0 cmd.Parameters.Append cmd.CreateParameter(p, 200, 1, 64, codeVal) Set rs cmd.Execute()CommandType 1 是 adCmdText告诉命令对象按 SQL 文本解析?是参数占位符CreateParameter 四个参数分别是参数名、数据类型、输入输出方向、长度、值。200 是 adVarChar64 是字段最大长度1 是输入参数。参数化之后输入里的单引号会被当成数据而不是 SQL 边界。GM 后台只要把登录、查渠道、发卡、改配置这几处 SQL 全改成参数化注入风险就消去大半。5.3 登录态和角色校验每个后台页面都必须执行GM 系统经常出现这种问题admin/index.asp 检查了登录admin/grant.asp 漏查导致能猜到路径就能调用发奖接口。解决办法是写一个公共的权限校验文件比如 inc/auth.asp% If Session(gm_id) Or Session(gm_role) 2 Then Response.Status 403 Forbidden Response.End End If %然后在每个后台页面最顶部加一句!--#include fileinc/auth.asp--。一要严格检查 gm_id 是否存在二要看角色等级比如 gm_role 小于 2 不允许访问发卡接口。注意 include 必须放在任何 Response.Write 输出之前否则经典 ASP 一旦输出正文Response.Status 就设置不生效了。校验文件本身不能放在 uploads 这类可写目录下否则等于白设。5.4 发码和奖励操作必须写审计日志GM 系统跑起来后最难追责的是“谁在什么时候发了什么码”。所以在发卡、发奖、改配置三处写审计日志是整个系统上线前最低的兜底要求。审计表可以设计成下面这样CREATE TABLE t_audit ( log_id INT IDENTITY(1,1) PRIMARY KEY, gm_id INT NOT NULL, action_type VARCHAR(20) NOT NULL, target_value VARCHAR(100), ip_addr VARCHAR(50), op_time DATETIME DEFAULT GETDATE() );写日志的代码要跟业务代码放在同一个事务里业务成功才提交日志避免出现“卡发出去了但日志没有记录”的空窗。IP 地址取法在经典 ASP 里惯用Request.ServerVariables(REMOTE_ADDR)如果前面挂了负载均衡则要取 X-Forwarded-For 的第一个值否则记下来全是代理地址追责就失效了。6. 验证技巧给 v6.0 做一次 60 秒冒烟测试部署完成、进生产之前我的习惯是压缩出一套 60 秒的冒烟测试用最少的请求把整条链路打一遍。6.1 先确认首页与登录接口状态码用 PowerShell 直接请求不需要浏览器$base http://127.0.0.1 (Invoke-WebRequest $base/index.asp -UseBasicParsing).StatusCode $body { username testgm; password tmp123; act login } $r Invoke-WebRequest $base/admin/login.asp -Method Post -Body $body -SessionVariable gmSession -UseBasicParsing if ($r.Content -match 管理后台|欢迎) { 登录成功 } else { 登录失败 }SessionVariable把本次会话的 Cookie 存进变量下一个请求带上-WebSession $gmSession就能保持登录态。检查的最终标志不是状态码而是内容里出现菜单关键字因为很多经典 ASP 页面即使校验失败也会返回 200只是内容变成登录框。6.2 生成一个激活码并核验数据库流水用一个临时 GM 账号进入发卡页走一遍批量生成$gen Invoke-WebRequest $base/admin/cdkey_batch.asp -Method Post -Body { num 5; channel test } -WebSession $gmSession -UseBasicParsing $gen.Content | Select-String [A-Z0-9]{16}只要能匹配到 16 位大写字母数字组合说明页面执行链路通。再查一下数据库里有没有对应记录sqlcmd -S . -d GMDB -Q SELECT code, gm_id, channel, create_time FROM t_cdkey WHERE channeltest如果是 Access则用“打开数据库文件 - 查表”的方式核验。这一步同时验证了写入表和生成函数是否正常。6.3 用畸形文件探测上传防护是否生效最后一条直接提交一个伪装成图片的 .asp 文件看防护是否拦截$form { file Get-Item C:\tmp\shell.asp } $up Invoke-WebRequest $base/admin/upload_banner.asp -Method Post -Form $form -WebSession $gmSession -UseBasicParsing $up.Content -match 不允许|failed返回内容包含拒绝关键字为正常如果返回了保存路径说明扩展名校验被绕过。绕过后再加随机文件名和目录禁执行检查重点不放在“能不能传”而是“传了之后能不能执行”。这最后一步通过上传安全才真正闭环。冒烟测试的脚本建议直接存成 ps1 文件每次发版后原样重跑一遍。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →