这是一份系统性的Web渗透测试学习笔记,涵盖前端基础、后端开发、数据库操作等核心知识。通过理论与实践相结合的方式,帮助初学者建立完整的Web安全知识体系。
顺序阅读,先理解前端基础,再学习后端逻辑,最后掌握数据库操作。
课件地址:https://git\.inmind\-lab\.com/aaronxu/security\-book
笔记地址: https://notes\.iproute\.cn/s/065a4c88
网络安全是保障公司业务正常运行,软件及其运行系统中的数据不因偶然的或者恶意原因来遭到破坏,更改和泄露,系统能够连续的可靠的正常运行,网络服务不中断。
(待补充)
(待补充)
(待补充)
HTML 基础结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 如果出现乱码,查看是否是格式问题,可能为"ASCII" -->
<meta http-equiv="refresh" content="30">
<!-- 每隔30秒来刷新网页 -->
<meta http-equiv="refresh" content="30;url=https://www.baidu.com">
<!-- 每隔30秒,刷新网页并跳转到百度的网站 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我是标题</title>
</head>
<body>
我是正文内容
</body>
</html>
常用标签:
<p></p> — 显示文字段落
<a href="/``https://www.baidu.com``">百度</a> — 跳转网站标签,超链接
<img src="/``https://www.baidu.com/img/bd_logo1.png``" alt="百度logo"> — 图片连接
<meta http-equiv="refresh" content="3;url=``https://www.baidu.com``"> — 刷新页面,并跳转网页
标题标签:
<h1>我是一级标题</h1>
<h2>我是二级标题</h2>
<h3>我是三级标题</h3>
<h4>我是四级标题</h4>
<h5>我是五级标题</h5>
表格:
<table>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
<tr>
<td>王厅长</td>
<td rowspan="3">20</td> <!-- 合并单元行 -->
<td colspan="2">男</td> <!-- 合并单元列 -->
<td>爱好</td>
</tr>
<tr>
<td>王厅长</td>
<td>20</td>
<td>男</td>
</tr>
<tr>
<td>王厅长</td>
<td>20</td>
<td>男</td>
</tr>
</table>
前端 HTML:
<h1 style="text-shadow: 2px 2px 5px blue">欢迎登录</h1>
<form action="login.php" method="post">
<!-- 将数据提交到后端的php文件中 -->
<input type="text" placeholder="请输入用户名">
<input type="password" placeholder="请输入密码">
<input type="submit" value="登录">
</form>
后端 PHP:
<?php
header("Content-type:text/html;charset=utf-8");
// 接受用户输入
// $_REQUEST 是全局变量,可以接受用户输入
// 当网页进行跳转后,用户输入的数据会保存到$_REQUEST中
// $_REQUEST是一个数组,可以通过下标访问数组中的元素
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
if ($username == "admin" && $password == "1") {
echo "登录成功";
} else if ($username == "user01" && $password == "2") {
echo "登录成功";
} else {
echo "登录失败";
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>欢迎登录</title>
<style>
:root{--primary:#6366f1;--primary-hover:#818cf8;--primary-dark:#4f46e5;--purple:#7c3aed;--success:#22c55e;--error:#ef4444;--glass:rgba(255,255,255,.04);--border:rgba(255,255,255,.08);--border-h:rgba(255,255,255,.15);--t1:#f1f5f9;--t2:#94a3b8;--t3:#475569;--ease:cubic-bezier(.16,1,.3,1);--spring:cubic-bezier(.34,1.56,.64,1)}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
html{-webkit-font-smoothing:antialiased}
body{font-family:'Segoe UI',system-ui,sans-serif;min-height:100vh;display:flex;justify-content:center;align-items:center;background:#020617;color:var(--t1);overflow:hidden;position:relative}
.bg{position:fixed;inset:0;z-index:0;pointer-events:none}
.bg-g{position:absolute;inset:0;background:radial-gradient(ellipse 80% 50% at 50% -20%,rgba(99,102,241,.25),transparent),radial-gradient(ellipse 60% 40% at 100% 0%,rgba(139,92,246,.18),transparent),radial-gradient(ellipse 50% 80% at 0% 50%,rgba(59,130,246,.12),transparent)}
.bg-grid{position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,.025) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.025) 1px,transparent 1px);background-size:60px 60px;mask-image:radial-gradient(ellipse 80% 50% at 50% 0%,black,transparent);-webkit-mask-image:radial-gradient(ellipse 80% 50% at 50% 0%,black,transparent)}
.glow{position:fixed;border-radius:50%;filter:blur(80px);pointer-events:none;z-index:1;opacity:.35}
.g1{width:400px;height:400px;top:-100px;right:-100px;background:var(--primary);animation:o1 20s ease-in-out infinite}
.g2{width:350px;height:350px;bottom:-80px;left:-80px;background:var(--purple);animation:o2 25s ease-in-out infinite}
@keyframes o1{0%,100%{transform:translate(0,0) scale(1)}25%{transform:translate(-50px,80px) scale(1.1)}50%{transform:translate(-100px,20px) scale(.9)}75%{transform:translate(-30px,-50px) scale(1.05)}}
@keyframes o2{0%,100%{transform:translate(0,0) scale(1)}25%{transform:translate(60px,-40px) scale(1.1)}50%{transform:translate(30px,-80px) scale(.95)}75%{transform:translate(-40px,-20px) scale(1.08)}}
.particles{position:fixed;inset:0;z-index:2;overflow:hidden;pointer-events:none}
.particle{position:absolute;border-radius:50%;background:rgba(255,255,255,.25);animation:float var(--d) var(--dl) infinite linear}
@keyframes float{0%{transform:translateY(100vh);opacity:0}10%{opacity:1}90%{opacity:1}100%{transform:translateY(-100vh);opacity:0}}
.wrapper{position:relative;z-index:10;width:100%;max-width:440px;padding:20px;animation:slideUp .8s var(--ease) forwards;opacity:0}
@keyframes slideUp{from{opacity:0;transform:translateY(60px) scale(.95);filter:blur(10px)}to{opacity:1;transform:translateY(0) scale(1);filter:blur(0)}}
.card{background:var(--glass);backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border:1px solid var(--border);border-radius:1.5rem;padding:48px 40px;position:relative;overflow:hidden;transition:all .3s ease}
.card::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent)}
.card::after{content:'';position:absolute;inset:0;border-radius:inherit;background:radial-gradient(circle at 50% 0%,rgba(99,102,241,.08),transparent 60%);pointer-events:none}
.card:hover{border-color:var(--border-h);box-shadow:0 0 40px rgba(99,102,241,.12);transform:translateY(-2px)}
.logo{width:56px;height:56px;margin:0 auto 20px;background:linear-gradient(135deg,var(--primary),var(--purple));border-radius:1rem;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(99,102,241,.3);animation:logoF 6s ease-in-out infinite}
.logo svg{width:28px;height:28px;fill:#fff}
@keyframes logoF{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
.header{text-align:center;margin-bottom:36px}
.header h1{font-size:26px;font-weight:700;margin-bottom:8px;letter-spacing:-.02em}
.header p{font-size:14px;color:var(--t2);letter-spacing:.05em}
.group{margin-bottom:20px}
.label{display:block;font-size:13px;font-weight:500;color:var(--t2);margin-bottom:8px;transition:color .2s}
.group:focus-within .label{color:var(--primary-hover)}
.input-wrap{position:relative;display:flex;align-items:center}
.input-icon{position:absolute;left:16px;width:20px;height:20px;color:var(--t3);pointer-events:none;transition:all .2s;z-index:2}
.group:focus-within .input-icon{color:var(--primary-hover);transform:scale(1.1)}
.input{width:100%;height:52px;padding:0 18px 0 48px;background:rgba(255,255,255,.05);border:1.5px solid rgba(255,255,255,.1);border-radius:.75rem;font-size:15px;font-family:inherit;color:var(--t1);transition:all .2s;outline:none}
.input::placeholder{color:var(--t3);transition:all .2s}
.input:hover{border-color:rgba(255,255,255,.2);background:rgba(255,255,255,.07)}
.input:focus{border-color:var(--primary);background:rgba(255,255,255,.08);box-shadow:0 0 0 4px rgba(99,102,241,.15),0 4px 16px rgba(0,0,0,.2);transform:translateY(-1px)}
.input:focus::placeholder{color:var(--t2);transform:translateX(4px)}
.input.error{border-color:var(--error);box-shadow:0 0 0 4px rgba(239,68,68,.15)}
.pw-toggle{position:absolute;right:16px;width:20px;height:20px;color:var(--t3);cursor:pointer;background:none;border:none;padding:4px;transition:all .2s;z-index:2;display:flex;align-items:center;justify-content:center}
.pw-toggle:hover{color:var(--t2);transform:scale(1.1)}
.pw-toggle svg{width:100%;height:100%}
.pw-toggle .icon-hide{display:none}
.pw-toggle.active .icon-show{display:none}
.pw-toggle.active .icon-hide{display:block}
.err-msg{display:none;font-size:12px;color:var(--error);margin-top:6px;padding-left:4px}
.err-msg.show{display:block;animation:shake .3s ease-in-out}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
.options{display:flex;justify-content:space-between;align-items:center;margin-bottom:28px;flex-wrap:wrap;gap:8px}
.chk{display:flex;align-items:center;gap:8px;cursor:pointer}
.chk input{display:none}
.chk-box{width:18px;height:18px;border:1.5px solid #475569;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:all .15s;background:transparent}
.chk-box svg{width:12px;height:12px;fill:#fff;opacity:0;transform:scale(0);transition:all .15s}
.chk input:checked+.chk-box{background:var(--primary);border-color:var(--primary)}
.chk input:checked+.chk-box svg{opacity:1;transform:scale(1)}
.chk-label{font-size:13px;color:var(--t2);user-select:none}
.forgot{font-size:13px;color:var(--primary-hover);text-decoration:none;transition:all .2s;position:relative}
.forgot::after{content:'';position:absolute;bottom:-2px;left:0;width:0;height:1.5px;background:var(--primary-hover);transition:width .2s}
.forgot:hover{color:#a5b4fc}
.forgot:hover::after{width:100%}
.btn{width:100%;height:52px;background:linear-gradient(135deg,var(--primary-dark),var(--purple));color:#fff;border:none;border-radius:.75rem;font-size:15px;font-weight:600;font-family:inherit;letter-spacing:.05em;cursor:pointer;position:relative;overflow:hidden;transition:all .2s;display:flex;align-items:center;justify-content:center;gap:8px}
.btn::before{content:'';position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent);transition:left .5s ease}
.btn:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(99,102,241,.4),0 4px 8px rgba(0,0,0,.2)}
.btn:hover::before{left:100%}
.btn:active{transform:translateY(0)}
.btn:disabled{opacity:.7;cursor:not-allowed;transform:none;box-shadow:none}
.btn-text{transition:all .2s}
.btn-loader{position:absolute;width:24px;height:24px;border:3px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;opacity:0;transition:opacity .2s}
.btn.loading .btn-text{opacity:0;transform:scale(.8)}
.btn.loading .btn-loader{opacity:1;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.divider{display:flex;align-items:center;gap:16px;margin:28px 0;color:#475569;font-size:12px;font-weight:500;text-transform:uppercase;letter-spacing:.1em}
.divider::before,.divider::after{content:'';flex:1;height:1px;background:linear-gradient(90deg,transparent,#1e293b,transparent)}
.socials{display:flex;gap:12px}
.social-btn{flex:1;height:48px;display:flex;align-items:center;justify-content:center;gap:8px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:.75rem;color:var(--t2);font-size:14px;font-family:inherit;font-weight:500;cursor:pointer;transition:all .2s}
.social-btn:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);transform:translateY(-2px);box-shadow:0 4px 12px rgba(0,0,0,.2)}
.social-btn:active{transform:translateY(0)}
.social-btn svg{width:20px;height:20px}
.footer{text-align:center;margin-top:28px;font-size:14px;color:var(--t2)}
.footer a{color:var(--primary-hover);text-decoration:none;font-weight:500;transition:all .2s;position:relative}
.footer a::after{content:'';position:absolute;bottom:-2px;left:0;width:0;height:1.5px;background:var(--primary-hover);transition:width .2s}
.footer a:hover{color:#a5b4fc}
.footer a:hover::after{width:100%}
.toast{position:fixed;top:24px;right:24px;z-index:1000;padding:14px 22px;background:rgba(30,41,59,.95);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);border-radius:.75rem;color:var(--t1);font-size:14px;box-shadow:0 20px 25px -5px rgba(0,0,0,.3);transform:translateX(120%);transition:transform .5s var(--spring);display:flex;align-items:center;gap:10px}
.toast.show{transform:translateX(0)}
.toast.success{border-left:4px solid var(--success)}
.toast.error{border-left:4px solid var(--error)}
.toast svg{width:18px;height:18px;flex-shrink:0}
.toast.success svg{color:var(--success)}
.toast.error svg{color:var(--error)}
.input:focus-visible,.btn:focus-visible,.social-btn:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}}
@media(max-width:480px){.wrapper{padding:16px}.card{padding:36px 24px}.header h1{font-size:22px}.input,.btn{height:48px}.socials{flex-direction:column}.glow{opacity:.2}.g1{width:250px;height:250px}.g2{width:200px;height:200px}}
@media(max-width:360px){.card{padding:28px 20px}.header{margin-bottom:28px}.options{flex-direction:column;align-items:flex-start;gap:12px}}
</style>
</head>
<body>
<div class="bg"><div class="bg-g"></div><div class="bg-grid"></div></div>
<div class="glow g1"></div>
<div class="glow g2"></div>
<div class="particles" id="particles"></div>
<div class="toast" id="toast">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/></svg>
<span id="toastMsg"></span>
</div>
<div class="wrapper">
<div class="card">
<div class="header">
<div class="logo">
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
</div>
<h1>欢迎回来</h1>
<p>请登录您的账户</p>
</div>
<form id="loginForm" action="login.php" method="post" novalidate>
<div class="group">
<label class="label" for="username">用户名</label>
<div class="input-wrap">
<svg class="input-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<input type="text" id="username" name="username" class="input" placeholder="请输入用户名" autocomplete="username" required>
</div>
<div class="err-msg" id="usernameError">请输入用户名</div>
</div>
<div class="group">
<label class="label" for="password">密码</label>
<div class="input-wrap">
<svg class="input-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
<input type="password" id="password" name="password" class="input" placeholder="请输入密码" autocomplete="current-password" required>
<button type="button" class="pw-toggle" id="pwToggle" aria-label="显示密码">
<svg class="icon-show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
<svg class="icon-hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
</button>
</div>
<div class="err-msg" id="passwordError">请输入密码</div>
</div>
<div class="options">
<label class="chk" tabindex="0">
<input type="checkbox" name="remember">
<span class="chk-box"><svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg></span>
<span class="chk-label">记住我</span>
</label>
<a href="#" class="forgot">忘记密码?</a>
</div>
<button type="submit" class="btn" id="submitBtn">
<span class="btn-text">登 录</span>
<span class="btn-loader"></span>
</button>
</form>
<div class="divider">或</div>
<div class="socials">
<button type="button" class="social-btn" onclick="showToast('微信登录开发中','error')">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.045c.133 0 .241-.108.241-.245 0-.06-.024-.118-.04-.177l-.325-1.233a.492.492 0 0 1 .177-.553C23.21 18.308 24 16.704 24 14.896c0-3.418-3.021-5.961-7.062-6.038zM14.5 13.93c.535 0 .969.44.969.983a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.983.97-.983zm4.844 0c.535 0 .969.44.969.983a.976.976 0 0 1-.97.983.976.976 0 0 1-.968-.983c0-.542.434-.983.969-.983z"/></svg>
微信
</button>
<button type="button" class="social-btn" onclick="showToast('QQ登录开发中','error')">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12.003 2c-2.265 0-6.29 1.364-6.29 7.325v1.195S3.55 14.96 3.55 17.474c0 .665.17 1.025.281 1.025.114 0 .902-.484 1.748-2.072 0 0-.18 2.197 1.904 3.967 0 0-1.77.495-1.77 1.182 0 .686 4.078.43 6.29.43 2.239 0 6.29.256 6.29-.43 0-.687-1.77-1.182-1.77-1.182 2.085-1.77 1.905-3.967 1.905-3.967.845 1.588 1.634 2.072 1.746 2.072.111 0 .283-.36.283-1.025 0-2.514-2.166-6.954-2.166-6.954V9.325C18.29 3.364 14.268 2 12.003 2z"/></svg>
QQ
</button>
</div>
<div class="footer">
还没有账号?<a href="register.html">立即注册</a>
</div>
</div>
</div>
<script>
(function(){
var c=document.getElementById('particles'),n=window.innerWidth<480?15:30;
for(var i=0;i<n;i++){var p=document.createElement('div');p.className='particle';var s=Math.random()*4+2;p.style.cssText='width:'+s+'px;height:'+s+'px;left:'+Math.random()*100+'%;--d:'+(Math.random()*15+10)+'s;--dl:'+Math.random()*10+'s;opacity:'+Math.random()*.3;c.appendChild(p)}
})();
function showToast(msg,type){var t=document.getElementById('toast'),m=document.getElementById('toastMsg');t.className='toast '+type;m.textContent=msg;t.classList.add('show');setTimeout(function(){t.classList.remove('show')},3000)}
(function(){var btn=document.getElementById('pwToggle'),inp=document.getElementById('password');btn.addEventListener('click',function(){var is=inp.type==='password';inp.type=is?'text':'password';btn.classList.toggle('active');btn.setAttribute('aria-label',is?'隐藏密码':'显示密码')})})();
document.querySelectorAll('.input').forEach(function(el){el.addEventListener('focus',function(){var e=this.parentElement.parentElement.querySelector('.err-msg');if(e){e.classList.remove('show')}this.classList.remove('error')})});
(function(){var form=document.getElementById('loginForm'),btn=document.getElementById('submitBtn');form.addEventListener('submit',function(e){var ok=true;var u=document.getElementById('username'),p=document.getElementById('password');if(!u.value.trim()){document.getElementById('usernameError').classList.add('show');u.classList.add('error');ok=false}else{document.getElementById('usernameError').classList.remove('show');u.classList.remove('error')}if(!p.value){document.getElementById('passwordError').classList.add('show');p.classList.add('error');ok=false}else{document.getElementById('passwordError').classList.remove('show');p.classList.remove('error')}if(!ok){e.preventDefault();return}btn.classList.add('loading');btn.disabled=true})})();
</script>
</body>
</html>
通用开源脚本语言。在一个 php 文件中可以包括以下内容:
PHP 文件可包含文本、HTML、JavaScript 代码和 PHP 代码
PHP 代码在服务器上执行,结果以纯 HTML 形式返回给浏览器
PHP 文件的默认文件扩展名是 ".php"
PHP 的使用:
PHP 可以生成动态页面内容
PHP 可以创建、打开、读取、写入、关闭服务器上的文件
PHP 可以收集表单数据
PHP 可以发送和接收 cookies
PHP 可以添加、删除、修改您的数据库中的数据
PHP 可以限制用户访问您的网站上的一些页面
PHP 可以加密数据
下载并解压 usbwebserver:
(请自行下载 usbwebserver 并解压,截图略)
PHP 变量与请求示例:
<?
// 定义变量
$a = "hello world";
echo $a;
// 接受用户输入
// $_REQUEST 是全局变量,可以接受用户输入
// 当网页进行跳转后,用户输入的数据会保存到$_REQUEST中
// $_REQUEST是一个数组,可以通过下标访问数组中的元素
// 数组是一个数据类型,可以包含多个数据
// php的数组都是以key,value的形式存储数据
// key是字符串,value是任意类型
// key是唯一的,value可以重复
// $_REQUEST['username'] 获取用户名
// $_REQUEST['password'] 获取密码
$res = $_REQUEST;
?>
<?php
header("Content-type:text/html;charset=utf-8"); //这行代码设置 HTTP 响应头,告诉浏览器返回的内容是什么类型。Content-type:text/html — 告诉浏览器这是 HTML 页面charset=utf-8 — 指定字符编码为 UTF-8,确保中文不会乱码没有这行的话,浏览器可能把中文显示成乱码或问号。
$username = isset($_POST['username']) ? $_POST['username'] : "";
$password = isset($_POST['password']) ? $_POST['password'] : "";
if ($username == "admin" && $password == "123456") {
echo "登录成功";
} else {
echo "登录失败";
}
?>
→ 返回关联数组: `["username"=>"admin", "password"=>"123456", "email"=>"admin@163.com", ...]`
→ 赋值给 `$row`,while 条件为 true → 进入循环体
→ `?>` 退出 PHP → 输出纯 HTML(用 `<?php echo $row["xxx"]?>` 插入值)→ `<?php` 回到 PHP
→ 循环 → 再取下一行 → 直到所有行取完,返回 null → while 条件为 false → 循环结束
<td><?php echo $row["username"]; ?></td>
<td><?php echo $row["password"]; ?></td>
<td><?php echo $row["email"]; ?></td>
**4. 编辑用户管理模块**
<td>
<div class="action-links">
<a href="user_edit.php?id=<?php echo $row['id']; ?>" class="action-link edit">
编辑
</a>
<a href="?action=delete&id=<?php echo $row['id']; ?>" class="action-link delete">
删除
</a>
</div>
</td>
后端连接数据库
用于博客的登录以及文章的储存
1.单击 PHPMyAdmin

2.创建数据库,并在数据库中,创建表格


Int 是 整型 id 不可重复,所以作为主键 索引为 : Primary
Varchar 是可变字符串 用来作为名称,密码,以及电子邮箱

<?php
header("Content-type:text/html;charset=utf-8");
$username = $_REQUEST["username"];
$password = $_REQUEST["password"];
// 连接数据库mysql
$host = "127.0.0.1";
$dbuser = "root";
$dbpassword = "usbw";
$database = "lyqblog";
$conn = mysqli_connect($host, $dbuser, $dbpassword, $database);
// 第1行 $conn = mysqli_connect(...)连接 MySQL 数据库,传入服务器地址、用户名、密码、数据库名,返回连接对象 $conn。相当于"打开数据库大门"。
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
}
// 查询数据库中的users表 , 并将$username和$password 作为条件查询
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $sql);
//第2行 $result = mysqli_query($conn, $sql)
//用已建立的连接 $conn 执行 SQL 查询语句 $sql,返回查询结果集 $result。相当于"向数据库提问并拿到答案"。
if (!$result){
echo "查询失败: " . mysqli_error($conn);
exit;
}
// 如果查询结果为空,则提示用户名或密码错误
if (mysqli_num_rows($result) == 0) {
echo "用户名或密码错误< a href = "login.html">返回登陆页面</a>";
exit;
} else {
echo "登录成功";
}
?>
会出现的bug: 在账户界面输入: ' or 1=1#
会出现万能密码的bug,因为MySQL的语句为 "SELECT * FROM users WHERE username = '$username' AND password = '$password'" 拼接过后是:
"SELECT * FROM users WHERE username = '$username' or 1=1 #' AND password = '$password'"
会执行 or 语句 , 判断 1=1 并且将密码的判断注释掉。会导致出现万能密码的情况。
<input type="hidden" name="login" value="1">
<button type="submit" class="btn" id="submitBtn">登 录</button>
// 使用input标记,通过使用name,提交login标记
<div class="fs"><input type="hidden" name="register" value="1"><button type="submit" class="btn" id="submitBtn"><span class="bt" id="btnText">注 册</span></button></div>
//使用同样方法,进行name,的register标记
<?php
header("Content-type:text/html;charset=utf-8");
// 连接数据库mysql
$host = "127.0.0.1";
$dbuser = "root";
$dbpassword = "usbw";
$database = "lyqblog";
$conn = mysqli_connect($host, $dbuser, $dbpassword, $database);
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
exit;
}
if (isset($_REQUEST["login"])){
//从前端接受用户名和密码,并进行查询操作
$username = $_REQUEST["username"];
$password = $_REQUEST["password"];
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $sql);
if (!$result){
echo "查询失败: " . mysqli_error($conn);
exit;
}
// 如果查询结果为空,则提示用户名或密码错误
if (mysqli_num_rows($result) == 0) {
echo "用户名或密码错误<a href='login.html'>返回登录页面</a>";
exit;
} else {
echo "登录成功";
}
}else if (isset($_REQUEST["register"])){
//判断用户名是否存在,或者邮箱是否存在
$username = $_REQUEST["username"];
$email = $_REQUEST["email"];
$sql = "SELECT * FROM users WHERE username = '$username' OR email = '$email'";
$result = mysqli_query($conn, $sql);
if (!$result){
echo "查询失败: " . mysqli_error($conn);
exit;
}
if (mysqli_num_rows($result) > 0) {
echo "用户名或邮箱已存在<a href='register.html'>返回注册页面</a>";
exit;
}
$password = $_REQUEST["password"];
$sql = "INSERT INTO users (username, password,email) VALUES ('$username', '$password','$email')";
$result = mysqli_query($conn, $sql);
if (!$result){
echo "注册失败: " . mysqli_error($conn);
exit;
}
echo "注册成功";
}else{
echo "操作错误";
}
// // 查询数据库中的users表 , 并将$username和$password 作为条件查询
// $sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// $result = mysqli_query($conn, $sql);
// if (!$result){
// echo "查询失败: " . mysqli_error($conn);
// exit;
// }
// // 如果查询结果为空,则提示用户名或密码错误
// if (mysqli_num_rows($result) == 0) {
// echo "用户名或密码错误<a href='login.html'>返回登录页面</a>";
// exit;
// } else {
// echo "登录成功";
// }
?>
服务器信息:
用户管理:
1.创建users_list.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网站后台管理-用户列表</title>
</head>
<body>
<table>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>邮箱</th>
<th>注册时间</th>
<th>操作</th>
</tr>
<tr>
<td>admin </td>
<td>123456</td>
<td><EMAIL></td>
<td><a href="user_edit.php?id=1">编辑</a> | <a href="?action=delete&id=1">删除</a><td>
</tr>
</table>
</body>
</html>
<a href="/user_edit.php?id=1">编辑</a> | <a href="/?action=delete&id=1">删除</a>
// 这段代码意思为: 编辑两个选项,对不同的网页输入不同的值
user_edit.php?id=1 网页地址 ? 值
action=delete&id=1 当前网页&输入值
2.添加连接数据库功能,并将查询结果进行打印:
<?php
header("Content-type:text/html;charset=utf-8");
// 连接数据库mysql
$host = "127.0.0.1";
$dbuser = "root";
$dbpassword = "usbw";
$database = "lyqblog";
$conn = mysqli_connect($host, $dbuser, $dbpassword, $database);
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
exit;
}
//获取users表中的所有数据
$sql = "SELECT * FROM users";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "查询失败: " . mysqli_error($conn);
exit;
}
//将查询的数据一行行进行输出
//mysql_fetch_assoc函数是将查询的数据以关联数组的形式返回,数组的key是字段名,value是字段值
while ($row = mysqli_fetch_assoc($result)) {
echo "<p>".$row["username"].":".$row["email"].":".$row["password"]."</p>";
}
//关闭数据库连接
mysqli_close($conn);
结果:

3.将此模块添加到main.php
代码段实例:
<tbody>
<?php
// 连接数据库mysql
$host = "127.0.0.1";
$dbuser = "root";
$dbpassword = "usbw";
$database = "lyqblog";
$conn = mysqli_connect($host, $dbuser, $dbpassword, $database);
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
exit;
}
//获取users表中的所有数据
$sql = "SELECT * FROM users";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "查询失败: " . mysqli_error($conn);
exit;
}
//将查询的数据一行行进行输出
//mysql_fetch_assoc函数是将查询的数据以关联数组的形式返回,数组的key是字段名,value是字段值
while ($row = mysqli_fetch_assoc($result)) {
?>
<tr>
<td><?php echo $row["username"]; ?></td>
<td><?php echo $row["password"]; ?></td>
<td><?php echo $row["email"]; ?></td>
<td>
<div class="action-links">
<a href="user_edit.php?id=1" class="action-link edit">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
编辑
</a>
<a href="?action=delete&id=1" class="action-link delete">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
</path>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
删除
</a>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
1.mysqli_fetch_assoc() 每次从结果集取一行
↓
返回关联数组: ["username"=>"admin", "password"=>"123456", "email"=>"admin@163.com", ...]
↓
赋值给 $row,while 条件为 true → 进入循环体
↓
?> 退出PHP → 输出纯HTML(用<?php echo $row["xxx"]?>插入值) → <?php回到PHP
↓
循环 → 再取下一行 → 直到所有行取完,返回 null → while 条件为 false → 循环结束
2. <td><?php echo $row["username"]; ?></td> <td><?php echo $row["password"]; ?></td> <td><?php echo $row["email"]; ?></td>
// 将从数据库中的数据再次使用php语言输出到前端。
4.编辑用管理模块
<td>
<div class="action-links">
<a href="user_edit.php?id=<?php echo $row["id"]; ?>" class="action-link edit">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
编辑
</a>
<a href="?action=delete&id=<?php echo $row["id"]; ?>" class="action-link delete">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
</path>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
删除
</a>
</div>
</td>
同样通过php语句将按键的id传入<a href="/user_edit.php?id=<?php echo $row["id"]; ?>" class="action-link edit">

创建db.php
<?php
//连接数据库
header("Content-type:text/html;charset=utf-8");
// 连接数据库mysql
$host = "127.0.0.1";
$dbuser = "root";
$dbpassword = "usbw";
$database = "lyqblog";
$conn = mysqli_connect($host, $dbuser, $dbpassword, $database);
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
exit;
}
// 模块化使用,方便直接从数据库中调用数据。
创建users_list.php
<?php include("db.php"); ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网站后台管理-用户列表</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--indigo: #6366f1; --indigo-l: #818cf8; --violet: #8b5cf6;
--cyan: #22d3ee; --emerald: #34d399; --rose: #fb7185;
--bg0: #050810; --bg1: #0a0e1a;
--sf1: rgba(255,255,255,0.018); --sf2: rgba(255,255,255,0.035);
--t1: #f0f4ff; --t2: #c4ccdf; --t3: #7a86a1; --t4: #4a5568;
--edge: rgba(255,255,255,0.06); --edge-h: rgba(255,255,255,0.12);
--r: 16px; --rl: 22px;
--ease: cubic-bezier(0.22,1,0.36,1);
--bounce: cubic-bezier(0.34,1.56,0.64,1);
}
* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; overflow-x:hidden; }
body {
font-family:'Inter',system-ui,-apple-system,sans-serif;
background:var(--bg0); color:var(--t1);
min-height:100vh; display:flex; flex-direction:column;
-webkit-font-smoothing:antialiased; overflow-x:hidden;
}
/* Ambient */
.ambient { position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.orb { position:absolute; border-radius:50%; filter:blur(120px); opacity:0.3; will-change:transform; }
.orb:nth-child(1) { width:600px; height:600px; background:var(--indigo); top:-20%; left:-10%; animation:od1 18s ease-in-out infinite alternate; }
.orb:nth-child(2) { width:500px; height:500px; background:var(--cyan); bottom:-15%; right:-8%; animation:od2 22s ease-in-out infinite alternate; }
.orb:nth-child(3) { width:350px; height:350px; background:var(--violet); top:40%; left:50%; opacity:0.15; animation:od3 15s ease-in-out infinite alternate; }
@keyframes od1 { to { transform:translate(120px,80px) scale(1.1); } }
@keyframes od2 { to { transform:translate(-100px,-60px) scale(0.9); } }
@keyframes od3 { to { transform:translate(-80px,60px) scale(1.15); } }
.ambient::after {
content:''; position:absolute; inset:0;
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(/%23n)' opacity='0.03'/%3E%3C/svg%3E");
background-size:256px; opacity:0.4; mix-blend-mode:overlay;
}
.grid-bg {
position:absolute; inset:0;
background-image:linear-gradient(rgba(255,255,255,0.015) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.015) 1px,transparent 1px);
background-size:60px 60px;
mask-image:radial-gradient(ellipse 70% 50% at 50% 30%,black,transparent);
}
/* Header */
.header {
position:sticky; top:0; z-index:100; height:58px; padding:0 28px;
display:flex; align-items:center; justify-content:space-between;
background:linear-gradient(180deg,rgba(15,20,35,0.92),rgba(10,14,26,0.88));
backdrop-filter:blur(30px) saturate(1.4) brightness(1.1);
border-bottom:1px solid var(--edge);
box-shadow:0 1px 0 rgba(255,255,255,0.03) inset,0 4px 24px rgba(0,0,0,0.3);
}
.header-title { font-size:14px; font-weight:600; display:flex; align-items:center; gap:10px; }
.beacon {
width:7px; height:7px; border-radius:50%; background:var(--emerald);
box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3);
animation:bpulse 2.5s ease-in-out infinite;
}
@keyframes bpulse { 0%,100%{box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3)} 50%{box-shadow:0 0 10px var(--emerald),0 0 28px rgba(52,211,153,0.5)} }
.header-user { display:flex; align-items:center; gap:10px; }
.avatar {
width:30px; height:30px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
display:flex; align-items:center; justify-content:center;
font-weight:700; font-size:11px; color:#fff; cursor:pointer; position:relative;
transition:transform 0.4s var(--bounce);
}
.avatar::after {
content:''; position:absolute; inset:-2px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
z-index:-1; opacity:0; filter:blur(6px); transition:opacity 0.4s;
}
.avatar:hover { transform:scale(1.12); }
.avatar:hover::after { opacity:0.6; }
.user-name { font-size:12px; font-weight:500; color:var(--t2); }
.logout-btn {
width:30px; height:30px; border-radius:8px; border:1px solid var(--edge);
background:rgba(255,255,255,0.03); color:var(--t3); cursor:pointer;
display:flex; align-items:center; justify-content:center;
transition:all 0.3s var(--ease); padding:0; margin-left:6px;
}
.logout-btn svg { width:14px; height:14px; }
.logout-btn:hover { background:rgba(251,113,133,0.1); border-color:rgba(251,113,133,0.3); color:var(--rose); transform:translateY(-1px); }
.logout-btn:active { transform:translateY(0); }
/* Layout */
.main-container { display:flex; flex:1; min-height:calc(100vh - 58px); position:relative; z-index:1; }
/* Sidebar */
.sidebar {
width:230px; flex-shrink:0;
background:linear-gradient(180deg,rgba(12,16,28,0.85),rgba(8,11,20,0.9));
backdrop-filter:blur(24px); border-right:1px solid var(--edge);
padding:20px 0; display:flex; flex-direction:column; position:relative;
}
.sidebar::after {
content:''; position:absolute; top:0; right:0; width:1px; height:100%;
background:linear-gradient(180deg,rgba(99,102,241,0.15),transparent 50%,rgba(34,211,238,0.1));
}
.nav-section { margin-bottom:24px; }
.nav-title { font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:var(--t4); padding:0 16px; margin-bottom:10px; }
.nav-links { display:flex; flex-direction:column; gap:2px; padding:0 6px; }
.nav-link {
display:flex; align-items:center; gap:10px; padding:10px 12px;
color:var(--t3); text-decoration:none; font-size:13px; font-weight:500;
border-radius:10px; transition:all 0.3s var(--ease); position:relative; overflow:hidden;
}
.nav-link::before {
content:''; position:absolute; inset:0;
background:linear-gradient(105deg,transparent 40%,rgba(255,255,255,0.04) 50%,transparent 60%);
transform:translateX(-100%); transition:transform 0.6s var(--ease);
}
.nav-link:hover::before { transform:translateX(100%); }
.nav-link:hover { background:var(--sf2); color:var(--t1); }
.nav-link.active {
background:linear-gradient(135deg,rgba(99,102,241,0.12),rgba(139,92,246,0.08));
color:var(--indigo-l); box-shadow:0 0 0 1px rgba(99,102,241,0.15) inset;
}
.nav-link.active::after {
content:''; position:absolute; left:0; top:50%; transform:translateY(-50%);
width:3px; height:18px; border-radius:0 3px 3px 0;
background:linear-gradient(180deg,var(--indigo),var(--violet));
box-shadow:0 0 10px rgba(99,102,241,0.4);
animation:igrow 0.35s var(--bounce);
}
@keyframes igrow { from{height:0;opacity:0} to{height:18px;opacity:1} }
.nav-link svg { width:16px; height:16px; flex-shrink:0; opacity:0.6; transition:all 0.3s var(--ease); }
.nav-link:hover svg, .nav-link.active svg { opacity:1; }
.nav-link.active svg { filter:drop-shadow(0 0 4px rgba(99,102,241,0.4)); }
/* Content */
.content { flex:1; padding:36px 40px; overflow-y:auto; }
.content-header { margin-bottom:32px; opacity:0; animation:rup 0.7s var(--ease) 0.1s forwards; }
.content-title {
font-size:28px; font-weight:800; letter-spacing:-0.03em;
background:linear-gradient(135deg,var(--t1) 30%,var(--indigo-l));
-webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text;
margin-bottom:6px;
}
.content-subtitle { font-size:13px; color:var(--t3); }
/* Table Container */
.table-container {
background:linear-gradient(165deg,rgba(255,255,255,0.04),rgba(255,255,255,0.01));
border:1px solid var(--edge); border-radius:var(--rl); padding:28px;
position:relative; overflow:hidden; opacity:0;
animation:creveal 0.7s var(--ease) 0.2s forwards;
}
.table-container::before {
content:''; position:absolute; top:0; left:0; right:0; height:1px;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.08) 20%,var(--indigo) 50%,rgba(255,255,255,0.08) 80%,transparent);
opacity:0; transition:opacity 0.5s;
}
.table-container::after {
content:''; position:absolute; inset:0;
background:radial-gradient(600px circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,0.04),transparent 40%);
opacity:0; transition:opacity 0.4s; pointer-events:none; border-radius:inherit;
}
.table-container:hover::before, .table-container:hover::after { opacity:1; }
.table-container:hover {
border-color:var(--edge-h);
box-shadow:0 8px 32px -8px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.04);
}
.table-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:24px; position:relative; z-index:1; }
.table-title { font-size:18px; font-weight:700; color:var(--t1); letter-spacing:-0.02em; }
.table-desc { font-size:12px; color:var(--t3); margin-top:4px; }
/* Table */
.data-table { width:100%; border-collapse:collapse; position:relative; z-index:1; }
.data-table th {
font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.08em;
color:var(--indigo-l); text-align:left; padding:14px 18px;
border-bottom:1px solid var(--edge); background:rgba(99,102,241,0.06);
}
.data-table th:first-child { border-radius:10px 0 0 0; }
.data-table th:last-child { border-radius:0 10px 0 0; }
.data-table td {
padding:14px 18px; border-bottom:1px solid var(--edge);
font-size:13px; color:var(--t2); transition:all 0.25s var(--ease);
}
.data-table tr { transition:all 0.25s var(--ease); }
.data-table tbody tr:hover {
background:linear-gradient(90deg,rgba(99,102,241,0.04),transparent);
}
.data-table tbody tr:hover td { color:var(--t1); }
.data-table tr:last-child td { border-bottom:none; }
/* Action Links */
.action-links { display:flex; gap:8px; }
.action-link {
display:inline-flex; align-items:center; gap:5px; padding:6px 14px;
border-radius:8px; font-size:12px; font-weight:500; text-decoration:none;
transition:all 0.3s var(--ease); border:1px solid transparent;
}
.action-link.edit {
background:rgba(99,102,241,0.08); color:var(--indigo-l);
border-color:rgba(99,102,241,0.15);
}
.action-link.edit:hover {
background:rgba(99,102,241,0.18); border-color:rgba(99,102,241,0.3);
transform:translateY(-1px); box-shadow:0 4px 12px rgba(99,102,241,0.15);
}
.action-link.delete {
background:rgba(251,113,133,0.08); color:var(--rose);
border-color:rgba(251,113,133,0.15);
}
.action-link.delete:hover {
background:rgba(251,113,133,0.18); border-color:rgba(251,113,133,0.3);
transform:translateY(-1px); box-shadow:0 4px 12px rgba(251,113,133,0.15);
}
.action-link svg { width:13px; height:13px; }
/* Add User Button */
.add-user-btn {
display:inline-flex; align-items:center; gap:8px; padding:10px 20px;
background:linear-gradient(135deg,rgba(52,211,153,0.15),rgba(52,211,153,0.08));
border:1px solid rgba(52,211,153,0.25); border-radius:10px;
color:var(--emerald); font-size:13px; font-weight:600; text-decoration:none;
transition:all 0.35s var(--ease); position:relative; overflow:hidden;
}
.add-user-btn::before {
content:''; position:absolute; top:0; left:-100%; width:100%; height:100%;
background:linear-gradient(90deg,transparent,rgba(52,211,153,0.15),transparent);
transition:left 0.6s var(--ease);
}
.add-user-btn:hover {
background:linear-gradient(135deg,rgba(52,211,153,0.25),rgba(52,211,153,0.15));
border-color:rgba(52,211,153,0.4); transform:translateY(-2px);
box-shadow:0 6px 20px rgba(52,211,153,0.2);
}
.add-user-btn:hover::before { left:100%; }
.add-user-btn:active { transform:translateY(0); transition-duration:0.1s; }
.add-user-btn svg { width:16px; height:16px; }
/* Animations */
@keyframes rup { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
@keyframes creveal { from{opacity:0;transform:translateY(24px) scale(0.96);filter:blur(4px)} to{opacity:1;transform:translateY(0) scale(1);filter:blur(0)} }
/* Scrollbar */
::-webkit-scrollbar { width:5px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.08); border-radius:3px; }
::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.14); }
/* Responsive */
@media(max-width:1100px) { .content{padding:28px 24px} }
@media(max-width:960px) { .sidebar{width:200px} }
@media(max-width:768px) {
.main-container{flex-direction:column}
.sidebar{width:100%;border-right:none;border-bottom:1px solid var(--edge);padding:10px 0}
.sidebar::after{display:none}
.nav-links{flex-direction:row;overflow-x:auto;padding:0 10px;gap:4px;-webkit-overflow-scrolling:touch}
.nav-link{padding:8px 14px;white-space:nowrap;font-size:12px;border-radius:8px}
.nav-link.active::after{display:none}
.content{padding:24px 18px}
.table-container{padding:16px}
.data-table{display:block;overflow-x:auto}
.content-title{font-size:22px}
.orb{opacity:0.2}
}
@media(max-width:480px) {
.header{padding:0 16px;height:52px}
.content{padding:18px 14px}
.table-header{flex-direction:column;align-items:flex-start;gap:8px}
.action-links{flex-direction:column;gap:6px}
.action-link{width:100%;justify-content:center}
}
/* Auth-gated elements: hidden by default, shown via JS when logged in */
.action-link, .add-user-btn { opacity:0; pointer-events:none; transition:opacity 0.3s var(--ease); }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after{animation-duration:0.01ms!important;animation-delay:0ms!important;transition-duration:0.01ms!important} .orb{animation:none!important} }
</style>
</head>
<body>
<div class="ambient">
<div class="orb"></div><div class="orb"></div><div class="orb"></div>
<div class="grid-bg"></div>
</div>
<header class="header">
<div class="header-title"><span class="beacon"></span>网站后台管理</div>
<div class="header-user">
<div class="avatar" id="headerAvatar">A</div>
<div class="user-name" id="headerUserName">管理员</div>
<button class="logout-btn" id="logoutBtn" title="退出登录">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
</button>
</div>
</header>
<div class="main-container">
<aside class="sidebar">
<div class="nav-section">
<div class="nav-title">导航菜单</div>
<div class="nav-links">
<a href="main.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
网站信息
</a>
<a href="articles.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
文章管理
</a>
<a href="users_list.php" class="nav-link active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
用户管理
</a>
</div>
</div>
</aside>
<main class="content">
<div class="content-header">
<h1 class="content-title">用户管理</h1>
<p class="content-subtitle">管理系统中的所有用户账户</p>
</div>
<div class="table-container">
<div class="table-header">
<div>
<div class="table-title">用户列表</div>
<div class="table-desc">显示所有注册用户的信息</div>
</div>
<a href="users_add.php" class="add-user-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
添加用户
</a>
</div>
<table class="data-table">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
//获取users表中的所有数据
$sql = "SELECT * FROM users";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "查询失败: " . mysqli_error($conn);
exit;
}
//将查询的数据一行行进行输出
//mysql_fetch_assoc函数是将查询的数据以关联数组的形式返回,数组的key是字段名,value是字段值
while ($row = mysqli_fetch_assoc($result)) {
?>
<tr>
<td><?php echo $row["id"]; ?></td>
<td><?php echo $row["username"]; ?></td>
<td><?php echo $row["password"]; ?></td>
<td><?php echo $row["email"]; ?></td>
<td>
<div class="action-links">
<a href="users_edit.php?id=<?php echo $row["id"]; ?>" class="action-link edit">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
编辑
</a>
<a href="users.php?del&id=<?php echo $row["id"]; ?>" class="action-link delete">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
</path>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
删除
</a>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</main>
</div>
<script>
// ── 前端登录状态检查与权限控制 ──
(function(){
var auth = localStorage.getItem('admin_auth');
if(!auth){
window.location.href = 'login.php';
return;
}
try{
var data = JSON.parse(auth);
var avatar = document.getElementById('headerAvatar');
var nameEl = document.getElementById('headerUserName');
if(data.username){
avatar.textContent = data.username.charAt(0).toUpperCase();
nameEl.textContent = data.username;
}
// 仅管理员(lyq)可见管理操作
if(data.username === 'lyq'){
document.querySelectorAll('.action-link, .add-user-btn').forEach(function(el){
el.style.opacity = '1';
el.style.pointerEvents = 'auto';
});
}
}catch(e){}
document.getElementById('logoutBtn').addEventListener('click', function(){
localStorage.removeItem('admin_auth');
window.location.href = 'login.php';
});
})();
// 3D light reflection tracking
document.querySelector('.table-container').addEventListener('mousemove', e => {
const r = e.currentTarget.getBoundingClientRect();
e.currentTarget.style.setProperty('--mx', ((e.clientX - r.left) / r.width * 100) + '%');
e.currentTarget.style.setProperty('--my', ((e.clientY - r.top) / r.height * 100) + '%');
});
// Scroll parallax
let ticking = false;
const orbs = document.querySelectorAll('.orb');
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
const y = window.scrollY;
orbs[0].style.transform = `translate(${y*0.02}px,${y*0.03}px)`;
orbs[1].style.transform = `translate(${-y*0.015}px,${-y*0.025}px)`;
orbs[2].style.transform = `translate(${y*0.01}px,${y*0.02}px)`;
ticking = false;
});
ticking = true;
}
}, { passive: true });
</script>
</body>
</html>
创建users_add.php
<?php include("db.php");?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网站后台管理-用户添加</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--indigo: #6366f1; --indigo-l: #818cf8; --violet: #8b5cf6;
--cyan: #22d3ee; --emerald: #34d399; --rose: #fb7185;
--bg0: #050810; --bg1: #0a0e1a;
--sf1: rgba(255,255,255,0.018); --sf2: rgba(255,255,255,0.035);
--t1: #f0f4ff; --t2: #c4ccdf; --t3: #7a86a1; --t4: #4a5568;
--edge: rgba(255,255,255,0.06); --edge-h: rgba(255,255,255,0.12);
--r: 16px; --rl: 22px;
--ease: cubic-bezier(0.22,1,0.36,1);
--bounce: cubic-bezier(0.34,1.56,0.64,1);
}
* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; overflow-x:hidden; }
body {
font-family:'Inter',system-ui,-apple-system,sans-serif;
background:var(--bg0); color:var(--t1);
min-height:100vh; display:flex; flex-direction:column;
-webkit-font-smoothing:antialiased; overflow-x:hidden;
}
/* Ambient */
.ambient { position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.orb { position:absolute; border-radius:50%; filter:blur(120px); opacity:0.3; will-change:transform; }
.orb:nth-child(1) { width:600px; height:600px; background:var(--indigo); top:-20%; left:-10%; animation:od1 18s ease-in-out infinite alternate; }
.orb:nth-child(2) { width:500px; height:500px; background:var(--cyan); bottom:-15%; right:-8%; animation:od2 22s ease-in-out infinite alternate; }
.orb:nth-child(3) { width:350px; height:350px; background:var(--violet); top:40%; left:50%; opacity:0.15; animation:od3 15s ease-in-out infinite alternate; }
@keyframes od1 { to { transform:translate(120px,80px) scale(1.1); } }
@keyframes od2 { to { transform:translate(-100px,-60px) scale(0.9); } }
@keyframes od3 { to { transform:translate(-80px,60px) scale(1.15); } }
.ambient::after {
content:''; position:absolute; inset:0;
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(/%23n)' opacity='0.03'/%3E%3C/svg%3E");
background-size:256px; opacity:0.4; mix-blend-mode:overlay;
}
.grid-bg {
position:absolute; inset:0;
background-image:linear-gradient(rgba(255,255,255,0.015) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.015) 1px,transparent 1px);
background-size:60px 60px;
mask-image:radial-gradient(ellipse 70% 50% at 50% 30%,black,transparent);
}
/* Header */
.header {
position:sticky; top:0; z-index:100; height:58px; padding:0 28px;
display:flex; align-items:center; justify-content:space-between;
background:linear-gradient(180deg,rgba(15,20,35,0.92),rgba(10,14,26,0.88));
backdrop-filter:blur(30px) saturate(1.4) brightness(1.1);
border-bottom:1px solid var(--edge);
box-shadow:0 1px 0 rgba(255,255,255,0.03) inset,0 4px 24px rgba(0,0,0,0.3);
}
.header-title { font-size:14px; font-weight:600; display:flex; align-items:center; gap:10px; }
.beacon {
width:7px; height:7px; border-radius:50%; background:var(--emerald);
box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3);
animation:bpulse 2.5s ease-in-out infinite;
}
@keyframes bpulse { 0%,100%{box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3)} 50%{box-shadow:0 0 10px var(--emerald),0 0 28px rgba(52,211,153,0.5)} }
.header-user { display:flex; align-items:center; gap:10px; }
.avatar {
width:30px; height:30px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
display:flex; align-items:center; justify-content:center;
font-weight:700; font-size:11px; color:#fff; cursor:pointer; position:relative;
transition:transform 0.4s var(--bounce);
}
.avatar::after {
content:''; position:absolute; inset:-2px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
z-index:-1; opacity:0; filter:blur(6px); transition:opacity 0.4s;
}
.avatar:hover { transform:scale(1.12); }
.avatar:hover::after { opacity:0.6; }
.user-name { font-size:12px; font-weight:500; color:var(--t2); }
.logout-btn {
width:30px; height:30px; border-radius:8px; border:1px solid var(--edge);
background:rgba(255,255,255,0.03); color:var(--t3); cursor:pointer;
display:flex; align-items:center; justify-content:center;
transition:all 0.3s var(--ease); padding:0; margin-left:6px;
}
.logout-btn svg { width:14px; height:14px; }
.logout-btn:hover { background:rgba(251,113,133,0.1); border-color:rgba(251,113,133,0.3); color:var(--rose); transform:translateY(-1px); }
.logout-btn:active { transform:translateY(0); }
/* Layout */
.main-container { display:flex; flex:1; min-height:calc(100vh - 58px); position:relative; z-index:1; }
/* Sidebar */
.sidebar {
width:230px; flex-shrink:0;
background:linear-gradient(180deg,rgba(12,16,28,0.85),rgba(8,11,20,0.9));
backdrop-filter:blur(24px); border-right:1px solid var(--edge);
padding:20px 0; display:flex; flex-direction:column; position:relative;
}
.sidebar::after {
content:''; position:absolute; top:0; right:0; width:1px; height:100%;
background:linear-gradient(180deg,rgba(99,102,241,0.15),transparent 50%,rgba(34,211,238,0.1));
}
.nav-section { margin-bottom:24px; }
.nav-title { font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:var(--t4); padding:0 16px; margin-bottom:10px; }
.nav-links { display:flex; flex-direction:column; gap:2px; padding:0 6px; }
.nav-link {
display:flex; align-items:center; gap:10px; padding:10px 12px;
color:var(--t3); text-decoration:none; font-size:13px; font-weight:500;
border-radius:10px; transition:all 0.3s var(--ease); position:relative; overflow:hidden;
}
.nav-link::before {
content:''; position:absolute; inset:0;
background:linear-gradient(105deg,transparent 40%,rgba(255,255,255,0.04) 50%,transparent 60%);
transform:translateX(-100%); transition:transform 0.6s var(--ease);
}
.nav-link:hover::before { transform:translateX(100%); }
.nav-link:hover { background:var(--sf2); color:var(--t1); }
.nav-link.active {
background:linear-gradient(135deg,rgba(99,102,241,0.12),rgba(139,92,246,0.08));
color:var(--indigo-l); box-shadow:0 0 0 1px rgba(99,102,241,0.15) inset;
}
.nav-link.active::after {
content:''; position:absolute; left:0; top:50%; transform:translateY(-50%);
width:3px; height:18px; border-radius:0 3px 3px 0;
background:linear-gradient(180deg,var(--indigo),var(--violet));
box-shadow:0 0 10px rgba(99,102,241,0.4);
animation:igrow 0.35s var(--bounce);
}
@keyframes igrow { from{height:0;opacity:0} to{height:18px;opacity:1} }
.nav-link svg { width:16px; height:16px; flex-shrink:0; opacity:0.6; transition:all 0.3s var(--ease); }
.nav-link:hover svg, .nav-link.active svg { opacity:1; }
.nav-link.active svg { filter:drop-shadow(0 0 4px rgba(99,102,241,0.4)); }
/* Content */
.content { flex:1; padding:36px 40px; overflow-y:auto; display:flex; justify-content:center; }
.content-inner { width:100%; max-width:600px; }
.content-header { margin-bottom:32px; opacity:0; animation:rup 0.7s var(--ease) 0.1s forwards; }
.content-title {
font-size:28px; font-weight:800; letter-spacing:-0.03em;
background:linear-gradient(135deg,var(--t1) 30%,var(--indigo-l));
-webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text;
margin-bottom:6px;
}
.content-subtitle { font-size:13px; color:var(--t3); }
/* Form Card */
.form-card {
background:linear-gradient(165deg,rgba(255,255,255,0.04),rgba(255,255,255,0.01));
border:1px solid var(--edge); border-radius:var(--rl); padding:32px;
position:relative; overflow:hidden; opacity:0;
animation:creveal 0.7s var(--ease) 0.2s forwards;
}
.form-card::before {
content:''; position:absolute; top:0; left:0; right:0; height:1px;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.08) 20%,var(--indigo) 50%,rgba(255,255,255,0.08) 80%,transparent);
opacity:0; transition:opacity 0.5s;
}
.form-card::after {
content:''; position:absolute; inset:0;
background:radial-gradient(600px circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,0.04),transparent 40%);
opacity:0; transition:opacity 0.4s; pointer-events:none; border-radius:inherit;
}
.form-card:hover::before, .form-card:hover::after { opacity:1; }
.form-card:hover { border-color:var(--edge-h); box-shadow:0 8px 32px -8px rgba(0,0,0,0.5); }
/* Form Elements */
.form-group { margin-bottom:20px; position:relative; z-index:1; }
.form-label {
display:block; font-size:11px; font-weight:600; text-transform:uppercase;
letter-spacing:0.08em; color:var(--t3); margin-bottom:8px;
}
.form-input {
width:100%; padding:12px 16px; font-size:14px; font-family:inherit;
color:var(--t1); background:rgba(255,255,255,0.03);
border:1px solid var(--edge); border-radius:10px;
outline:none; transition:all 0.3s var(--ease);
}
.form-input::placeholder { color:var(--t4); }
.form-input:focus {
border-color:rgba(99,102,241,0.4);
background:rgba(99,102,241,0.04);
box-shadow:0 0 0 3px rgba(99,102,241,0.08);
}
.form-input:hover:not(:focus) {
border-color:var(--edge-h);
background:rgba(255,255,255,0.04);
}
.form-hint {
font-size:11px; color:var(--t4); margin-top:6px; display:flex;
align-items:center; gap:4px;
}
.form-hint svg { width:12px; height:12px; opacity:0.6; }
/* Section Divider */
.form-divider {
height:1px; background:var(--edge); margin:24px 0; position:relative; z-index:1;
}
.form-section-title {
font-size:10px; font-weight:600; text-transform:uppercase;
letter-spacing:0.1em; color:var(--indigo-l); margin-bottom:16px;
position:relative; z-index:1;
}
/* Submit Button */
.btn-submit {
width:100%; padding:14px 24px; font-size:14px; font-weight:600;
font-family:inherit; color:#fff; border:none; border-radius:10px;
cursor:pointer; position:relative; z-index:1; overflow:hidden;
background:linear-gradient(135deg,var(--indigo),var(--violet));
transition:all 0.3s var(--ease);
box-shadow:0 4px 16px rgba(99,102,241,0.25);
}
.btn-submit::before {
content:''; position:absolute; top:0; left:-100%; width:100%; height:100%;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);
transition:left 0.5s var(--ease);
}
.btn-submit:hover {
transform:translateY(-2px);
box-shadow:0 8px 24px rgba(99,102,241,0.35);
}
.btn-submit:hover::before { left:100%; }
.btn-submit:active { transform:translateY(0); }
/* Button Group */
.btn-group {
margin-top:24px; position:relative; z-index:1;
}
.btn-primary {
width:100%; padding:14px 24px; font-size:14px; font-weight:600;
font-family:inherit; color:#fff; border:none; border-radius:10px;
cursor:pointer; position:relative; overflow:hidden;
background:linear-gradient(135deg,var(--indigo),var(--violet));
transition:all 0.3s var(--ease);
box-shadow:0 4px 16px rgba(99,102,241,0.25);
}
.btn-primary::before {
content:''; position:absolute; top:0; left:-100%; width:100%; height:100%;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);
transition:left 0.5s var(--ease);
}
.btn-primary:hover {
transform:translateY(-2px);
box-shadow:0 8px 24px rgba(99,102,241,0.35);
}
.btn-primary:hover::before { left:100%; }
.btn-primary:active { transform:translateY(0); }
.btn-primary:active::after {
content:''; position:absolute; inset:0; border-radius:inherit;
background:radial-gradient(circle at 50% 50%,rgba(255,255,255,0.2),transparent 60%);
animation:ripple 0.4s var(--ease);
}
/* Back Link */
.back-link {
display:inline-flex; align-items:center; gap:6px; margin-top:16px;
font-size:12px; color:var(--t3); text-decoration:none;
transition:all 0.3s var(--ease); position:relative; z-index:1;
}
.back-link:hover { color:var(--indigo-l); transform:translateX(-2px); }
.back-link svg { width:14px; height:14px; }
/* Animations */
@keyframes rup { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
@keyframes creveal { from{opacity:0;transform:translateY(24px) scale(0.96);filter:blur(4px)} to{opacity:1;transform:translateY(0) scale(1);filter:blur(0)} }
@keyframes ripple { from{transform:scale(0);opacity:1} to{transform:scale(2.5);opacity:0} }
/* Scrollbar */
::-webkit-scrollbar { width:5px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.08); border-radius:3px; }
::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.14); }
/* Responsive */
@media(max-width:1100px) { .content{padding:28px 24px} }
@media(max-width:960px) { .sidebar{width:200px} }
@media(max-width:768px) {
.main-container{flex-direction:column}
.sidebar{width:100%;border-right:none;border-bottom:1px solid var(--edge);padding:10px 0}
.sidebar::after{display:none}
.nav-links{flex-direction:row;overflow-x:auto;padding:0 10px;gap:4px;-webkit-overflow-scrolling:touch}
.nav-link{padding:8px 14px;white-space:nowrap;font-size:12px;border-radius:8px}
.nav-link.active::after{display:none}
.content{padding:24px 18px}
.form-card{padding:24px}
.content-title{font-size:22px}
.orb{opacity:0.2}
}
@media(max-width:480px) { .header{padding:0 16px;height:52px} .content{padding:18px 14px} }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after{animation-duration:0.01ms!important;animation-delay:0ms!important;transition-duration:0.01ms!important} .orb{animation:none!important} }
</style>
</head>
<body>
<div class="ambient">
<div class="orb"></div><div class="orb"></div><div class="orb"></div>
<div class="grid-bg"></div>
</div>
<header class="header">
<div class="header-title"><span class="beacon"></span>网站后台管理</div>
<div class="header-user">
<div class="avatar" id="headerAvatar">A</div>
<div class="user-name" id="headerUserName">管理员</div>
<button class="logout-btn" id="logoutBtn" title="退出登录">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
</button>
</div>
</header>
<div class="main-container">
<aside class="sidebar">
<div class="nav-section">
<div class="nav-title">导航菜单</div>
<div class="nav-links">
<a href="main.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
网站信息
</a>
<a href="articles.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
文章管理
</a>
<a href="users_list.php" class="nav-link active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
用户管理
</a>
</div>
</div>
</aside>
<main class="content">
<div class="content-inner">
<div class="content-header">
<h1 class="content-title">添加用户</h1>
<p class="content-subtitle">添加用户账户信息</p>
</div>
<?php
// 添加用户页面不需要查询现有用户信息
// 表单字段为空,由用户输入新数据
?>
<div class="form-card">
<form action="users.php" method="post">
<input type="hidden" name="register" value="1">
<div class="form-section-title">基本信息</div>
<div class="form-group">
<label class="form-label" for="username">用户名</label>
<input class="form-input" type="text" id="username" name="username" placeholder="请输入用户名" required>
</div>
<div class="form-group">
<label class="form-label" for="email">邮箱</label>
<input class="form-input" type="email" id="email" name="email" placeholder="请输入邮箱" required>
</div>
<div class="form-divider"></div>
<div class="form-section-title">密码设置</div>
<div class="form-group">
<label class="form-label" for="password">密码</label>
<input class="form-input" type="password" id="password" name="password" placeholder="请输入密码" required>
</div>
<div class="form-group">
<label class="form-label" for="repassword">确认密码</label>
<input class="form-input" type="password" id="repassword" name="repassword" placeholder="请再次确认密码" required>
</div>
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="添加" name="add">
</div>
</form>
</div>
<a href="users_list.php" class="back-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
返回用户列表
</a>
</div>
</main>
</div>
<script>
// ── 前端登录状态检查 ──
(function(){
var auth = localStorage.getItem('admin_auth');
if(!auth){ window.location.href = 'login.php'; return; }
try{
var data = JSON.parse(auth);
var avatar = document.getElementById('headerAvatar');
var nameEl = document.getElementById('headerUserName');
if(data.username){
avatar.textContent = data.username.charAt(0).toUpperCase();
nameEl.textContent = data.username;
}
// 仅管理员(lyq)可访问此页面
if(data.username !== 'lyq'){
window.location.href = 'main.php';
return;
}
}catch(e){}
document.getElementById('logoutBtn').addEventListener('click', function(){
localStorage.removeItem('admin_auth');
window.location.href = 'login.php';
});
})();
// 3D light reflection
document.querySelector('.form-card').addEventListener('mousemove', e => {
const r = e.currentTarget.getBoundingClientRect();
e.currentTarget.style.setProperty('--mx', ((e.clientX - r.left) / r.width * 100) + '%');
e.currentTarget.style.setProperty('--my', ((e.clientY - r.top) / r.height * 100) + '%');
});
// Scroll parallax
let ticking = false;
const orbs = document.querySelectorAll('.orb');
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
const y = window.scrollY;
orbs[0].style.transform = `translate(${y*0.02}px,${y*0.03}px)`;
orbs[1].style.transform = `translate(${-y*0.015}px,${-y*0.025}px)`;
orbs[2].style.transform = `translate(${y*0.01}px,${y*0.02}px)`;
ticking = false;
});
ticking = true;
}
}, { passive: true });
// Input focus ripple
document.querySelectorAll('.form-input').forEach(input => {
input.addEventListener('focus', () => {
input.parentElement.style.transform = 'translateX(2px)';
setTimeout(() => input.parentElement.style.transform = '', 150);
});
});
// Button hover light tracking
const btn = document.querySelector('.btn-primary');
if (btn) {
btn.addEventListener('mousemove', e => {
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
btn.style.background = `radial-gradient(circle at ${x}px ${y}px, rgba(255,255,255,0.15), transparent 50%), linear-gradient(135deg, var(--indigo), var(--violet))`;
});
btn.addEventListener('mouseleave', () => {
btn.style.background = 'linear-gradient(135deg, var(--indigo), var(--violet))';
});
// Form submission loading state
btn.closest('form').addEventListener('submit', function() {
btn.style.transform = 'scale(0.95)';
btn.style.opacity = '0.8';
btn.value = '保存中...';
setTimeout(() => {
btn.style.transform = '';
btn.style.opacity = '';
btn.value = '保存';
}, 1500);
});
}
</script>
</body>
</html>
创建users_edit
<?php include("db.php");?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网站后台管理-用户编辑</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--indigo: #6366f1; --indigo-l: #818cf8; --violet: #8b5cf6;
--cyan: #22d3ee; --emerald: #34d399; --rose: #fb7185;
--bg0: #050810; --bg1: #0a0e1a;
--sf1: rgba(255,255,255,0.018); --sf2: rgba(255,255,255,0.035);
--t1: #f0f4ff; --t2: #c4ccdf; --t3: #7a86a1; --t4: #4a5568;
--edge: rgba(255,255,255,0.06); --edge-h: rgba(255,255,255,0.12);
--r: 16px; --rl: 22px;
--ease: cubic-bezier(0.22,1,0.36,1);
--bounce: cubic-bezier(0.34,1.56,0.64,1);
}
* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; overflow-x:hidden; }
body {
font-family:'Inter',system-ui,-apple-system,sans-serif;
background:var(--bg0); color:var(--t1);
min-height:100vh; display:flex; flex-direction:column;
-webkit-font-smoothing:antialiased; overflow-x:hidden;
}
/* Ambient */
.ambient { position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.orb { position:absolute; border-radius:50%; filter:blur(120px); opacity:0.3; will-change:transform; }
.orb:nth-child(1) { width:600px; height:600px; background:var(--indigo); top:-20%; left:-10%; animation:od1 18s ease-in-out infinite alternate; }
.orb:nth-child(2) { width:500px; height:500px; background:var(--cyan); bottom:-15%; right:-8%; animation:od2 22s ease-in-out infinite alternate; }
.orb:nth-child(3) { width:350px; height:350px; background:var(--violet); top:40%; left:50%; opacity:0.15; animation:od3 15s ease-in-out infinite alternate; }
@keyframes od1 { to { transform:translate(120px,80px) scale(1.1); } }
@keyframes od2 { to { transform:translate(-100px,-60px) scale(0.9); } }
@keyframes od3 { to { transform:translate(-80px,60px) scale(1.15); } }
.ambient::after {
content:''; position:absolute; inset:0;
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(/%23n)' opacity='0.03'/%3E%3C/svg%3E");
background-size:256px; opacity:0.4; mix-blend-mode:overlay;
}
.grid-bg {
position:absolute; inset:0;
background-image:linear-gradient(rgba(255,255,255,0.015) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.015) 1px,transparent 1px);
background-size:60px 60px;
mask-image:radial-gradient(ellipse 70% 50% at 50% 30%,black,transparent);
}
/* Header */
.header {
position:sticky; top:0; z-index:100; height:58px; padding:0 28px;
display:flex; align-items:center; justify-content:space-between;
background:linear-gradient(180deg,rgba(15,20,35,0.92),rgba(10,14,26,0.88));
backdrop-filter:blur(30px) saturate(1.4) brightness(1.1);
border-bottom:1px solid var(--edge);
box-shadow:0 1px 0 rgba(255,255,255,0.03) inset,0 4px 24px rgba(0,0,0,0.3);
}
.header-title { font-size:14px; font-weight:600; display:flex; align-items:center; gap:10px; }
.beacon {
width:7px; height:7px; border-radius:50%; background:var(--emerald);
box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3);
animation:bpulse 2.5s ease-in-out infinite;
}
@keyframes bpulse { 0%,100%{box-shadow:0 0 6px var(--emerald),0 0 16px rgba(52,211,153,0.3)} 50%{box-shadow:0 0 10px var(--emerald),0 0 28px rgba(52,211,153,0.5)} }
.header-user { display:flex; align-items:center; gap:10px; }
.avatar {
width:30px; height:30px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
display:flex; align-items:center; justify-content:center;
font-weight:700; font-size:11px; color:#fff; cursor:pointer; position:relative;
transition:transform 0.4s var(--bounce);
}
.avatar::after {
content:''; position:absolute; inset:-2px; border-radius:50%;
background:conic-gradient(from 45deg,var(--indigo),var(--violet),var(--cyan),var(--indigo));
z-index:-1; opacity:0; filter:blur(6px); transition:opacity 0.4s;
}
.avatar:hover { transform:scale(1.12); }
.avatar:hover::after { opacity:0.6; }
.user-name { font-size:12px; font-weight:500; color:var(--t2); }
.logout-btn {
width:30px; height:30px; border-radius:8px; border:1px solid var(--edge);
background:rgba(255,255,255,0.03); color:var(--t3); cursor:pointer;
display:flex; align-items:center; justify-content:center;
transition:all 0.3s var(--ease); padding:0; margin-left:6px;
}
.logout-btn svg { width:14px; height:14px; }
.logout-btn:hover { background:rgba(251,113,133,0.1); border-color:rgba(251,113,133,0.3); color:var(--rose); transform:translateY(-1px); }
.logout-btn:active { transform:translateY(0); }
/* Layout */
.main-container { display:flex; flex:1; min-height:calc(100vh - 58px); position:relative; z-index:1; }
/* Sidebar */
.sidebar {
width:230px; flex-shrink:0;
background:linear-gradient(180deg,rgba(12,16,28,0.85),rgba(8,11,20,0.9));
backdrop-filter:blur(24px); border-right:1px solid var(--edge);
padding:20px 0; display:flex; flex-direction:column; position:relative;
}
.sidebar::after {
content:''; position:absolute; top:0; right:0; width:1px; height:100%;
background:linear-gradient(180deg,rgba(99,102,241,0.15),transparent 50%,rgba(34,211,238,0.1));
}
.nav-section { margin-bottom:24px; }
.nav-title { font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:var(--t4); padding:0 16px; margin-bottom:10px; }
.nav-links { display:flex; flex-direction:column; gap:2px; padding:0 6px; }
.nav-link {
display:flex; align-items:center; gap:10px; padding:10px 12px;
color:var(--t3); text-decoration:none; font-size:13px; font-weight:500;
border-radius:10px; transition:all 0.3s var(--ease); position:relative; overflow:hidden;
}
.nav-link::before {
content:''; position:absolute; inset:0;
background:linear-gradient(105deg,transparent 40%,rgba(255,255,255,0.04) 50%,transparent 60%);
transform:translateX(-100%); transition:transform 0.6s var(--ease);
}
.nav-link:hover::before { transform:translateX(100%); }
.nav-link:hover { background:var(--sf2); color:var(--t1); }
.nav-link.active {
background:linear-gradient(135deg,rgba(99,102,241,0.12),rgba(139,92,246,0.08));
color:var(--indigo-l); box-shadow:0 0 0 1px rgba(99,102,241,0.15) inset;
}
.nav-link.active::after {
content:''; position:absolute; left:0; top:50%; transform:translateY(-50%);
width:3px; height:18px; border-radius:0 3px 3px 0;
background:linear-gradient(180deg,var(--indigo),var(--violet));
box-shadow:0 0 10px rgba(99,102,241,0.4);
animation:igrow 0.35s var(--bounce);
}
@keyframes igrow { from{height:0;opacity:0} to{height:18px;opacity:1} }
.nav-link svg { width:16px; height:16px; flex-shrink:0; opacity:0.6; transition:all 0.3s var(--ease); }
.nav-link:hover svg, .nav-link.active svg { opacity:1; }
.nav-link.active svg { filter:drop-shadow(0 0 4px rgba(99,102,241,0.4)); }
/* Content */
.content { flex:1; padding:36px 40px; overflow-y:auto; display:flex; justify-content:center; }
.content-inner { width:100%; max-width:600px; }
.content-header { margin-bottom:32px; opacity:0; animation:rup 0.7s var(--ease) 0.1s forwards; }
.content-title {
font-size:28px; font-weight:800; letter-spacing:-0.03em;
background:linear-gradient(135deg,var(--t1) 30%,var(--indigo-l));
-webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text;
margin-bottom:6px;
}
.content-subtitle { font-size:13px; color:var(--t3); }
/* Form Card */
.form-card {
background:linear-gradient(165deg,rgba(255,255,255,0.04),rgba(255,255,255,0.01));
border:1px solid var(--edge); border-radius:var(--rl); padding:32px;
position:relative; overflow:hidden; opacity:0;
animation:creveal 0.7s var(--ease) 0.2s forwards;
}
.form-card::before {
content:''; position:absolute; top:0; left:0; right:0; height:1px;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.08) 20%,var(--indigo) 50%,rgba(255,255,255,0.08) 80%,transparent);
opacity:0; transition:opacity 0.5s;
}
.form-card::after {
content:''; position:absolute; inset:0;
background:radial-gradient(600px circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,0.04),transparent 40%);
opacity:0; transition:opacity 0.4s; pointer-events:none; border-radius:inherit;
}
.form-card:hover::before, .form-card:hover::after { opacity:1; }
.form-card:hover { border-color:var(--edge-h); box-shadow:0 8px 32px -8px rgba(0,0,0,0.5); }
/* Form Elements */
.form-group { margin-bottom:20px; position:relative; z-index:1; }
.form-label {
display:block; font-size:11px; font-weight:600; text-transform:uppercase;
letter-spacing:0.08em; color:var(--t3); margin-bottom:8px;
}
.form-input {
width:100%; padding:12px 16px; font-size:14px; font-family:inherit;
color:var(--t1); background:rgba(255,255,255,0.03);
border:1px solid var(--edge); border-radius:10px;
outline:none; transition:all 0.3s var(--ease);
}
.form-input::placeholder { color:var(--t4); }
.form-input:focus {
border-color:rgba(99,102,241,0.4);
background:rgba(99,102,241,0.04);
box-shadow:0 0 0 3px rgba(99,102,241,0.08);
}
.form-input:hover:not(:focus) {
border-color:var(--edge-h);
background:rgba(255,255,255,0.04);
}
.form-hint {
font-size:11px; color:var(--t4); margin-top:6px; display:flex;
align-items:center; gap:4px;
}
.form-hint svg { width:12px; height:12px; opacity:0.6; }
/* Section Divider */
.form-divider {
height:1px; background:var(--edge); margin:24px 0; position:relative; z-index:1;
}
.form-section-title {
font-size:10px; font-weight:600; text-transform:uppercase;
letter-spacing:0.1em; color:var(--indigo-l); margin-bottom:16px;
position:relative; z-index:1;
}
/* Submit Button */
.btn-submit {
width:100%; padding:14px 24px; font-size:14px; font-weight:600;
font-family:inherit; color:#fff; border:none; border-radius:10px;
cursor:pointer; position:relative; z-index:1; overflow:hidden;
background:linear-gradient(135deg,var(--indigo),var(--violet));
transition:all 0.3s var(--ease);
box-shadow:0 4px 16px rgba(99,102,241,0.25);
}
.btn-submit::before {
content:''; position:absolute; top:0; left:-100%; width:100%; height:100%;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);
transition:left 0.5s var(--ease);
}
.btn-submit:hover {
transform:translateY(-2px);
box-shadow:0 8px 24px rgba(99,102,241,0.35);
}
.btn-submit:hover::before { left:100%; }
.btn-submit:active { transform:translateY(0); }
/* Button Group */
.btn-group {
margin-top:24px; position:relative; z-index:1;
}
.btn-primary {
width:100%; padding:14px 24px; font-size:14px; font-weight:600;
font-family:inherit; color:#fff; border:none; border-radius:10px;
cursor:pointer; position:relative; overflow:hidden;
background:linear-gradient(135deg,var(--indigo),var(--violet));
transition:all 0.3s var(--ease);
box-shadow:0 4px 16px rgba(99,102,241,0.25);
}
.btn-primary::before {
content:''; position:absolute; top:0; left:-100%; width:100%; height:100%;
background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);
transition:left 0.5s var(--ease);
}
.btn-primary:hover {
transform:translateY(-2px);
box-shadow:0 8px 24px rgba(99,102,241,0.35);
}
.btn-primary:hover::before { left:100%; }
.btn-primary:active { transform:translateY(0); }
.btn-primary:active::after {
content:''; position:absolute; inset:0; border-radius:inherit;
background:radial-gradient(circle at 50% 50%,rgba(255,255,255,0.2),transparent 60%);
animation:ripple 0.4s var(--ease);
}
/* Back Link */
.back-link {
display:inline-flex; align-items:center; gap:6px; margin-top:16px;
font-size:12px; color:var(--t3); text-decoration:none;
transition:all 0.3s var(--ease); position:relative; z-index:1;
}
.back-link:hover { color:var(--indigo-l); transform:translateX(-2px); }
.back-link svg { width:14px; height:14px; }
/* Animations */
@keyframes rup { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
@keyframes creveal { from{opacity:0;transform:translateY(24px) scale(0.96);filter:blur(4px)} to{opacity:1;transform:translateY(0) scale(1);filter:blur(0)} }
@keyframes ripple { from{transform:scale(0);opacity:1} to{transform:scale(2.5);opacity:0} }
/* Scrollbar */
::-webkit-scrollbar { width:5px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.08); border-radius:3px; }
::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.14); }
/* Responsive */
@media(max-width:1100px) { .content{padding:28px 24px} }
@media(max-width:960px) { .sidebar{width:200px} }
@media(max-width:768px) {
.main-container{flex-direction:column}
.sidebar{width:100%;border-right:none;border-bottom:1px solid var(--edge);padding:10px 0}
.sidebar::after{display:none}
.nav-links{flex-direction:row;overflow-x:auto;padding:0 10px;gap:4px;-webkit-overflow-scrolling:touch}
.nav-link{padding:8px 14px;white-space:nowrap;font-size:12px;border-radius:8px}
.nav-link.active::after{display:none}
.content{padding:24px 18px}
.form-card{padding:24px}
.content-title{font-size:22px}
.orb{opacity:0.2}
}
@media(max-width:480px) { .header{padding:0 16px;height:52px} .content{padding:18px 14px} }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after{animation-duration:0.01ms!important;animation-delay:0ms!important;transition-duration:0.01ms!important} .orb{animation:none!important} }
</style>
</head>
<body>
<div class="ambient">
<div class="orb"></div><div class="orb"></div><div class="orb"></div>
<div class="grid-bg"></div>
</div>
<header class="header">
<div class="header-title"><span class="beacon"></span>网站后台管理</div>
<div class="header-user">
<div class="avatar" id="headerAvatar">A</div>
<div class="user-name" id="headerUserName">管理员</div>
<button class="logout-btn" id="logoutBtn" title="退出登录">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
</button>
</div>
</header>
<div class="main-container">
<aside class="sidebar">
<div class="nav-section">
<div class="nav-title">导航菜单</div>
<div class="nav-links">
<a href="main.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
网站信息
</a>
<a href="articles.php" class="nav-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
文章管理
</a>
<a href="users_list.php" class="nav-link active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
用户管理
</a>
</div>
</div>
</aside>
<main class="content">
<div class="content-inner">
<div class="content-header">
<h1 class="content-title">编辑用户</h1>
<p class="content-subtitle">修改用户账户信息</p>
</div>
<?php
// 根据传递的id,获取表中的各个信息
$userid = $_REQUEST["id"];
$sql = "SELECT * FROM users WHERE id = '$userid'";
$result = mysqli_query($conn, $sql);
if (!$result){
echo "查询失败: " . mysqli_error($conn);
exit;
}
$row = mysqli_fetch_assoc($result);
if ($row) {
$username = $row["username"];
$email = $row["email"];
}
?>
<div class="form-card">
<form action="users.php" method="post">
<div class="form-section-title">基本信息</div>
<div class="form-group">
<label class="form-label" for="username">用户名</label>
<input class="form-input" type="text" id="username" name="username" placeholder="请输入用户名" value="<?php echo htmlspecialchars(isset($username) ? $username : ''); ?>">
</div>
<div class="form-group">
<label class="form-label" for="email">邮箱</label>
<input class="form-input" type="email" id="email" name="email" placeholder="请输入邮箱" value="<?php echo htmlspecialchars(isset($email) ? $email : ''); ?>">
</div>
<div class="form-divider"></div>
<div class="form-section-title">密码修改</div>
<div class="form-group">
<label class="form-label" for="bepassword">原密码</label>
<input class="form-input" type="password" id="bepassword" name="bepassword" placeholder="请输入原密码">
</div>
<div class="form-group">
<label class="form-label" for="password">新密码</label>
<input class="form-input" type="password" id="password" name="password" placeholder="请输入新密码">
</div>
<div class="form-group">
<label class="form-label" for="repassword">确认密码</label>
<input class="form-input" type="password" id="repassword" name="repassword" placeholder="请再次输入新密码">
</div>
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="保存" name="change">
</div>
</form>
</div>
<a href="users_list.php" class="back-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
返回用户列表
</a>
</div>
</main>
</div>
<script>
// ── 前端登录状态检查 ──
(function(){
var auth = localStorage.getItem('admin_auth');
if(!auth){ window.location.href = 'login.php'; return; }
try{
var data = JSON.parse(auth);
var avatar = document.getElementById('headerAvatar');
var nameEl = document.getElementById('headerUserName');
if(data.username){
avatar.textContent = data.username.charAt(0).toUpperCase();
nameEl.textContent = data.username;
}
// 仅管理员(lyq)可访问此页面
if(data.username !== 'lyq'){
window.location.href = 'main.php';
return;
}
}catch(e){}
document.getElementById('logoutBtn').addEventListener('click', function(){
localStorage.removeItem('admin_auth');
window.location.href = 'login.php';
});
})();
// 3D light reflection
document.querySelector('.form-card').addEventListener('mousemove', e => {
const r = e.currentTarget.getBoundingClientRect();
e.currentTarget.style.setProperty('--mx', ((e.clientX - r.left) / r.width * 100) + '%');
e.currentTarget.style.setProperty('--my', ((e.clientY - r.top) / r.height * 100) + '%');
});
// Scroll parallax
let ticking = false;
const orbs = document.querySelectorAll('.orb');
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
const y = window.scrollY;
orbs[0].style.transform = `translate(${y*0.02}px,${y*0.03}px)`;
orbs[1].style.transform = `translate(${-y*0.015}px,${-y*0.025}px)`;
orbs[2].style.transform = `translate(${y*0.01}px,${y*0.02}px)`;
ticking = false;
});
ticking = true;
}
}, { passive: true });
// Input focus ripple
document.querySelectorAll('.form-input').forEach(input => {
input.addEventListener('focus', () => {
input.parentElement.style.transform = 'translateX(2px)';
setTimeout(() => input.parentElement.style.transform = '', 150);
});
});
// Button hover light tracking
const btn = document.querySelector('.btn-primary');
if (btn) {
btn.addEventListener('mousemove', e => {
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
btn.style.background = `radial-gradient(circle at ${x}px ${y}px, rgba(255,255,255,0.15), transparent 50%), linear-gradient(135deg, var(--indigo), var(--violet))`;
});
btn.addEventListener('mouseleave', () => {
btn.style.background = 'linear-gradient(135deg, var(--indigo), var(--violet))';
});
// Form submission loading state
btn.closest('form').addEventListener('submit', function() {
btn.style.transform = 'scale(0.95)';
btn.style.opacity = '0.8';
btn.value = '保存中...';
setTimeout(() => {
btn.style.transform = '';
btn.style.opacity = '';
btn.value = '保存';
}, 1500);
});
}
</script>
</body>
</html>
原理:
一句话解释: 攻击者通过在输入框中插入恶意 SQL 代码,欺骗数据库执行非预期操作。
假设有个登录查询:
SELECT * FROM users WHERE username = '用户输入' AND password = '用户输入';
正常输入:
用户名: zhangsan
密码: 123456
→ 生成的 SQL:
SELECT * FROM users WHERE username = 'zhangsan' AND password = '123456';
恶意输入:
用户名: ' OR 1=1 --
密码: 随便填
→ 生成的 SQL:
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = '随便填';
-- 是 SQL 注释,后面的内容被忽略。1=1 永远为真,所以无需密码就能登录任何账号。
| 危害 | 说明 |
|---|---|
| 🔓 绕过登录 | 无需密码进入系统 |
| 📤 窃取数据 | 导出用户表、密码、敏感信息 |
| 🗑️ 删库 | DROP TABLE users 清空整张表 |
| 🔧 篡改数据 | 修改价格、余额、权限等 |
| 🖥️ 服务器控制 | 通过数据库执行系统命令(高级攻击) |
1. 参数化查询(最有效)
# ❌ 危险:字符串拼接
query = f"SELECT * FROM users WHERE username = '{username}'"
# ✅ 安全:参数化
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
2. ORM 框架
# SQLAlchemy 自动防注入
User.query.filter_by(username=username).first()
3. 输入验证 — 过滤特殊字符('、--、; 等)
4. 最小权限 — 数据库账号只给必要的权限,禁用 DROP、EXEC 等
5. WAF 防火墙 — 拦截常见注入特征
永远不要信任用户输入,永远用参数化查询。
SQL 注入的根本问题是:代码和数据没有分离。
程序期望的输入:一个普通的字符串(用户名)
攻击者实际输入:一段可执行的 SQL 代码
数据库无法区分:哪些是指令,哪些是数据
原理: 用 UNION 把攻击者的查询结果拼接到正常结果后面。
-- 正常查询
SELECT name, price FROM products WHERE id = 1
-- 攻击输入:1 UNION SELECT username, password FROM users --
-- 最终执行:
SELECT name, price FROM products WHERE id = 1
UNION
SELECT username, password FROM users --
结果: 产品页变成了用户密码列表。
原理: 故意让 SQL 报错,错误信息中会泄露数据库内容。
-- 输入:' AND extractvalue(1, concat(0x7e, (SELECT version()))) --
-- 报错信息:
XPATH syntax error: '~5.7.34'
攻击者从错误信息中拿到了数据库版本号。
原理: 页面没有回显数据,但根据「页面正常/异常」来判断猜测是否正确。
-- 判断数据库名第一个字符是否为 'r'
' AND (SELECT substring(database(),1,1)) = 'r' --
-- 页面正常 → 猜对了,第一个字符是 'r'
-- 判断第二个字符
' AND (SELECT substring(database(),2,1)) = 'o' --
-- 页面正常 → 数据库名可能是 'root'...
像猜密码一样,一个字符一个字符地试。
原理: 页面完全没有变化,通过响应时间来判断。
-- 如果条件为真,延迟 3 秒响应
' AND IF(1=1, SLEEP(3), 0) --
-- 响应慢了 3 秒 → 条件为真
' AND IF((SELECT substring(database(),1,1)) = 'r', SLEEP(3), 0) --
-- 响应慢 → 第一个字符确实是 'r'
原理: 用分号 ; 执行多条 SQL 语句。
-- 输入:1; DROP TABLE users; --
-- 执行两条语句:
SELECT * FROM products WHERE id = 1;
DROP TABLE users;
后果: 用户表直接被删。
原理: 恶意输入先被「安全」地存入数据库,后续使用时再触发。
第一步:注册用户名 → admin'-- (存入数据库时被转义,安全)
第二步:修改密码功能读取该用户名 → 拼接到 SQL 中 → 触发注入
第三步:攻击者修改了真正 admin 的密码
最隐蔽的一种,因为存储时检查
数据库为层级结构
数据库基本代码回顾:
mysql> use lyqblog
Database changed
mysql> select * from users
->
-> ;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
| 9 | apiuser | api123 | api@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.01 sec)
mysql> select username from users
-> ;
+----------+
| username |
+----------+
| lyq |
| whc |
| dbw |
| admin |
| user1 |
| testuser |
| apiuser |
+----------+
7 rows in set (0.00 sec)
mysql> select 'lyqnb' from users
-> ;
+-------+
| lyqnb |
+-------+
| lyqnb |
| lyqnb |
| lyqnb |
| lyqnb |
| lyqnb |
| lyqnb |
| lyqnb |
+-------+
7 rows in set (0.00 sec)
mysql> select 1,2,4
-> ;
+---+---+---+
| 1 | 2 | 4 |
+---+---+---+
| 1 | 2 | 4 |
+---+---+---+
1 row in set (0.00 sec)
mysql> select * from users union select * from users ;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
| 9 | apiuser | api123 | api@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.00 sec)
mysql> select * from users union select 1,2,3,4;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
| 9 | apiuser | api123 | api@example.com |
| 1 | 2 | 3 | 4 |
+----+----------+-----------+-------------------+
8 rows in set (0.00 sec)
mysql> select * from users where username = '-1 ' union select 1 , 'admin',3,4;
+----+----------+----------+-------+
| id | username | password | email |
+----+----------+----------+-------+
| 1 | admin | 3 | 4 |
+----+----------+----------+-------+
1 row in set (0.00 sec)
mysql> select * from users where username = '' or 1=1 #' and password = "";
->
-> ;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
| 9 | apiuser | api123 | api@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.00 sec)
mysql> select * from users where username =''union select 1,'lyq',3,4#' and password='';
-> ;
+----+----------+----------+-------+
| id | username | password | email |
+----+----------+----------+-------+
| 1 | lyq | 3 | 4 |
+----+----------+----------+-------+
1 row in set (0.00 sec)
//两个表的列应该相同
mysql> select * from users order by 1
-> ;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
| 9 | apiuser | api123 | api@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.00 sec)
mysql> select * from users order by 3;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 1 | lyq | 1 | lyq@163.com |
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 9 | apiuser | api123 | api@example.com |
| 7 | user1 | password1 | user1@example.com |
| 8 | testuser | test123 | test@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.00 sec)
mysql> select * from users order by 4;
+----+----------+-----------+-------------------+
| id | username | password | email |
+----+----------+-----------+-------------------+
| 4 | whc | 1 | 123@123.com |
| 5 | dbw | 1 | 159@159.com |
| 6 | admin | admin123 | admin@example.com |
| 9 | apiuser | api123 | api@example.com |
| 1 | lyq | 1 | lyq@163.com |
| 8 | testuser | test123 | test@example.com |
| 7 | user1 | password1 | user1@example.com |
+----+----------+-----------+-------------------+
7 rows in set (0.00 sec)
XYCMS:
select * from xxx where id = 13 ;
1. 让语句进行报错
select * from xxx where id = 13';
使用orderby进行猜测,
而后
select * from users where id =-13 union select 1,2,3,4,5,6,7,8,9,10;
其中的数字可以替换为,一些查询操作。
进行初始化的设置
(root㉿kali)-[~]
└─# vim /etc/ssh/sshd_config
#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
vim /etc/passwd
root:x:0:0:root:/root:/usr/bin/bash
apt -y install docker.io
#配置镜像下载加速
vim /etc/docker/daemon.josn
{
"registry-mirrors": ["https://service-crproxy.onrender.com"],
"insecure-registries": ["service-crproxy.onrender.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
在远程主机中安装docker

修复步骤
按 Win + X,选择"Windows PowerShell (管理员)"或"终端 (管理员)"
powershell
复制
Remove-Item -Recurse -Force "$env:APPDATA\npm\node_modules\openclaw"
powershell
复制
npm install -g openclaw@latest
powershell
复制
openclaw --version
powershell
复制
openclaw gateway restart
可能遇到的问题
如果 npm install 报权限错误,尝试用管理员权限运行
如果网络问题导致下载慢,可以设置 npm 镜像源:
powershell
复制
npm config set registry https://registry\.npmmirror\.com
npm install -g openclaw@latest
完成这些步骤后回来告诉我,我帮你确认更新是否成功。
docker run -d -P harbor.iproute.cn:30080/course/xycms:latest
docker run -d -P 172.16.17.4:30080/course/xycms:latest