基于 ASP 与 TekRADIUS 的 PPPoE 密码自助修改方案
摘要
目的让用户能够自主修改拨号 PPPoE 密码。结合 经典 ASP 调用 TekRADIUS 外部 CLI 工具实现账号自助重置 ,本文将基于 ASP 如何通过 ADO 连接 SQL Server 验证原密码,并利用WScript.Shell调用 TekRADIUS 命令行工具trcli.exe完成账号属性的更新。
密码修改代码password-change.asp
<%
Option Explicit
Response.Buffer = True
Response.Charset = "UTF-8"
' -------------------------
' TekRADIUS trcli.exe 路径
' -------------------------
Const TRCLI_PATH = "C:\Program Files\TekRADIUS\trcli.exe"
' -------------------------
' 数据库配置
' -------------------------
Dim DB_SERVER, DB_NAME, DB_USER, DB_PASS
DB_SERVER = "1.1.1.1"
DB_NAME = "TekRADIUS"
DB_USER = "sa"
DB_PASS = "1111"
' -------------------------
' 工具函数
' -------------------------
Function TrimSafe(s)
If IsNull(s) Then
TrimSafe = ""
Else
TrimSafe = Trim(CStr(s))
End If
End Function
Sub Fail(msg)
Response.Write "<script>alert('" & Replace(msg,"'","\'") & "');history.back();</script>"
Response.End
End Sub
Sub Success(msg)
Response.Write "<script>alert('" & Replace(msg,"'","\'") & "');window.location='index.asp';</script>"
Response.End
End Sub
Function RunCmd(cmd)
Dim WshShell, execObj, output
Set WshShell = Server.CreateObject("WScript.Shell")
Set execObj = WshShell.Exec(cmd)
output = execObj.StdOut.ReadAll & vbCrLf & execObj.StdErr.ReadAll
RunCmd = output
End Function
' -------------------------
' 表单提交处理
' -------------------------
If Request.ServerVariables("REQUEST_METHOD") = "POST" Then
Dim username, oldpwd, newpwd, confpwd
username = TrimSafe(Request.Form("username"))
oldpwd = TrimSafe(Request.Form("oldpwd"))
newpwd = TrimSafe(Request.Form("newpwd"))
confpwd = TrimSafe(Request.Form("confpwd"))
If username = "" Or oldpwd = "" Or newpwd = "" Or confpwd = "" Then Fail "请填写所有字段!"
If newpwd <> confpwd Then Fail "新的密码与确认密码不一致!"
If Len(newpwd) < 6 Then Fail "密码至少需要 6 位字符!"
' -------------------------
' 检查账号是否存在 + 验证原密码
' -------------------------
Dim conn, cmd, rs
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Server=" & DB_SERVER & ";Database=" & DB_NAME & ";Uid=" & DB_USER & ";Pwd=" & DB_PASS & ";"
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandType = 1 ' adCmdText
cmd.CommandText = "SELECT Val FROM dbo.Users WHERE RTRIM(UserName)=? AND Attribute='ietf|2'"
cmd.Parameters.Append cmd.CreateParameter("", 202, 1, 64, username)
Set rs = cmd.Execute()
If rs.EOF Then
rs.Close
conn.Close
Fail "上网账号不存在!"
Else
Dim dbPwd
dbPwd = TrimSafe(rs("Val"))
If dbPwd <> oldpwd Then
rs.Close
conn.Close
Fail "上网密码错误!"
End If
End If
rs.Close
conn.Close
' -------------------------
' 调用 trcli.exe 修改密码
' -------------------------
Dim delCmd, addCmd
delCmd = "%comspec% /c """"" & TRCLI_PATH & """" & " -m " & username & " ""ietf|2"" check"""
RunCmd(delCmd)
addCmd = "%comspec% /c """"" & TRCLI_PATH & """" & " -a " & username & " ""ietf|2"" " & newpwd & " check"""
RunCmd(addCmd)
Success "上网密码修改成功!"
End If
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body{font-family:Arial, "Microsoft YaHei"; margin:30px;}
.form{max-width:420px; padding:18px; border:1px solid #ddd; border-radius:6px; box-shadow:0 2px 6px rgba(0,0,0,.05);}
.form h2{margin-top:0;}
.form label{display:block; margin:4px 0 2px;}
.form input[type=text], .form input[type=password]{width:100%; padding:8px; box-sizing:border-box;}
.form .btn{margin-top:12px; padding:8px 12px; cursor:pointer;}
</style>
<title>PPPoE上网账号_密码修改</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
margin: 0;
padding: 20px 0 0 0;
background-color: #f0f2f5;
}
.form {
width: 90%;
max-width: 420px;
margin: 0 auto;
padding: 30px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
background-color: #ffffff;
box-sizing: border-box;
text-align: left;
}
.form h2 {
margin-top: 0;
margin-bottom: 24px;
text-align: center;
color: #333333;
font-size: 22px;
font-weight: 600;
}
.form label {
display: block;
margin-bottom: 8px;
color: #555555;
font-weight: 500;
font-size: 14px;
}
.form input[type=text],
.form input[type=password] {
width: 100%;
padding: 12px;
margin-bottom: 14px;
border: 1px solid #dcdfe6;
border-radius: 8px;
box-sizing: border-box;
font-size: 14px;
transition: border-color 0.3s, box-shadow 0.3s;
}
.form input[type=text]:focus,
.form input[type=password]:focus {
outline: none;
border-color: #409eff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.form .btn {
width: 100%;
padding: 12px;
border: none;
border-radius: 8px;
background-color: #409eff;
color: white;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
}
.form .btn:hover { background-color: #66b1ff; }
.form .btn:active { background-color: #3a8ee6; transform: translateY(1px); }
.help-section {
display: flex;
justify-content: space-between;
margin-top: 16px;
font-weight: 500;
font-size: 14px;
}
.help-section a {
color: #555555;
text-decoration: none;
transition: color 0.3s, text-decoration 0.3s;
}
.help-section a:hover {
color: #3a8ee6;
text-decoration: underline;
}
@media (max-width: 400px) {
.form h2 { font-size: 20px; }
.help-section {
flex-direction: column;
align-items: center;
gap: 8px;
}
}
</style>
<script>
function validateForm(){
var u=document.getElementById('username').value.trim();
var op=document.getElementById('oldpwd').value;
var np=document.getElementById('newpwd').value;
var cp=document.getElementById('confpwd').value;
if(u===''||op===''||np===''||cp===''){alert('请填写所有字段!');return false;}
if(np!==cp){alert('新的密码与确认密码不一致!');return false;}
if(np.length<6){alert('密码至少需要 6 位!');return false;}
return true;
}
</script>
</head>
<body>
<div class="form">
<h2>PPPoE上网账号_密码修改</h2>
<form method="post" action="index.asp" onsubmit="return validateForm();">
<label for="username">上网帐号:</label>
<input id="username" name="username" type="text" maxlength="64" />
<label for="oldpwd">上网密码:</label>
<input id="oldpwd" name="oldpwd" type="password" maxlength="256" />
<label for="newpwd">新的密码:</label>
<input id="newpwd" name="newpwd" type="password" maxlength="256" />
<label for="confpwd">确认密码:</label>
<input id="confpwd" name="confpwd" type="password" maxlength="256" />
<input class="btn" type="submit" value="确 认 密 码 修 改" />
<p></p>
</form>
</div>
</body>
</html>
核心逻辑流程
整个流程可以分为三个阶段:
- 前端验证:通过 JavaScript 进行基础的非空和一致性校验。
- 身份核实:连接 SQL Server 数据库,核对
UserName对应的原密码(Attribute为ietf|2)。 - 系统更新:验证通过后,先删除旧属性,再添加新属性,确保 RADIUS 服务端配置即时生效。
安全改进建议 (Best Practices)
虽然这段代码已经实现了核心功能,但在生产环境中,建议关注以下几点:
- 明文存储风险: 代码中
SELECT Val表明密码在数据库中可能是明文存储的。建议在 TekRADIUS 配置中使用加密存储。 - HTTPS 必要性: 由于涉及密码传输,该页面必须部署在 HTTPS 协议下,否则账号密码极易在传输过程中被截获。
- 权限控制: 执行
WScript.Shell的 Web 账户(通常是 IIS AppPool 用户)需要有运行itrcli.exe的特定权限,务必遵循最小权限原则。 - 操作审计: 建议在修改成功后,将操作日志写入数据库,记录修改的时间和 IP 地址,以便日后溯源。
总结
这种“ASP + SQL + CLI”的架构虽然传统,但在特定内网管理工具的集成中非常高效。它不仅实现了 Web 与闭源二进制工具的联动,也提供了一个完整的闭环逻辑:输入校验→身份核实→状态更新→结果反馈。