Files
freeshop/login.php
T
2026-08-14 10:55:06 +08:00

133 lines
6.5 KiB
PHP

<?php
// 登录 / 注册
require __DIR__ . '/includes/init.php';
$pageTitle = __('login.title');
$next = $_GET['next'] ?? '';
$mode = $_GET['mode'] ?? 'login';
$invite = trim($_GET['inv'] ?? '');
$err = '';
$ok = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verifyCsrf();
if (isset($_POST['login'])) {
$u = trim($_POST['username'] ?? '');
$pw = $_POST['password'] ?? '';
$stmt = db()->prepare('SELECT * FROM ' . tn('users') . ' WHERE username = ?');
$stmt->execute([$u]);
$row = $stmt->fetch();
if ($row && password_verify($pw, $row['password'])) {
$_SESSION['user_id'] = $row['id'];
unset($_SESSION['csrf']);
redirect($next ?: 'index.php');
}
$err = __('login.err_login_failed');
}
if (isset($_POST['register'])) {
$u = trim($_POST['username'] ?? '');
$pw = $_POST['password'] ?? '';
$pw2 = $_POST['password2'] ?? '';
$em = trim($_POST['email'] ?? '');
$cap = strtoupper(trim($_POST['captcha'] ?? ''));
// 邀请码:优先使用表单填写,其次使用 URL 参数
$postInvite = isset($_POST['invite_code']) ? trim($_POST['invite_code']) : null;
$invite = $postInvite !== null ? $postInvite : trim($_GET['inv'] ?? '');
// 自研图形验证码:一次性校验后清空
$sessCap = isset($_SESSION['captcha']) ? strtoupper($_SESSION['captcha']) : '';
unset($_SESSION['captcha']);
if ($cap === '' || $cap !== $sessCap) {
$err = __('login.err_captcha_wrong');
}
elseif (strlen($u) < 3) $err = __('login.err_username_short');
elseif (strlen($pw) < 6) $err = __('login.err_password_short');
elseif ($pw !== $pw2) $err = __('login.err_password_mismatch');
elseif (!filter_var($em, FILTER_VALIDATE_EMAIL)) $err = __('login.err_email_invalid');
// 若用户在表单里手动填写了邀请码,则必须校验通过
elseif ($postInvite !== null && $postInvite !== '' && getInviterIdByCode($postInvite) === 0) {
$err = __('login.err_invite_invalid');
}
// 单 IP 每日最多注册 2 个账号
if ($err === '') {
$ip = getClientIp();
if (regCountToday($ip) >= 2) {
$err = __('login.err_ip_limit');
}
}
if ($err === '') {
$chk = db()->prepare('SELECT id FROM ' . tn('users') . ' WHERE username = ?');
$chk->execute([$u]);
if ($chk->fetch()) {
$err = __('login.err_username_exists');
} else {
$hash = password_hash($pw, PASSWORD_DEFAULT);
$myCode = genInviteCode();
db()->prepare('INSERT INTO ' . tn('users') . ' (username,password,email,reg_ip,invite_code,verified,created_at) VALUES (?,?,?,?,?,0,NOW())')
->execute([$u, $hash, $em, $ip, $myCode]);
$id = db()->lastInsertId();
// 邀请奖励:通过他人邀请码注册,给邀请人加积分
if ($invite !== '') {
$invId = getInviterIdByCode($invite);
if ($invId > 0 && $invId != $id) {
db()->prepare('UPDATE ' . tn('users') . ' SET invited_by = ? WHERE id = ?')
->execute([$invId, $id]);
$invPts = max(0, (int) getSetting('points_invite', '20'));
if ($invPts > 0) {
addPoints($invId, 'invite', $invPts, '邀请好友 ' . $u . ' 注册成功');
}
}
}
$_SESSION['user_id'] = $id;
// 发送邮箱验证邮件(不阻塞注册:失败也可正常使用)
$sendRes = sendVerifyMail($id);
$_SESSION['verify_notice'] = $sendRes['ok'] ? 'sent' : 'fail';
unset($_SESSION['csrf']);
redirect($next ?: 'index.php');
}
}
}
}
require 'includes/header.php';
?>
<section class="section auth-section">
<div class="auth-card">
<div class="auth-tabs">
<a href="login.php?mode=login" class="<?= $mode==='login'?'active':'' ?>"><?= __('login.tab_login') ?></a>
<a href="login.php?mode=register" class="<?= $mode==='register'?'active':'' ?>"><?= __('login.tab_register') ?></a>
</div>
<?php if ($err): ?><p class="form-err"><?= h($err) ?></p><?php endif; ?>
<?php if ($mode === 'login'): ?>
<form method="post" action="" class="auth-form">
<?= csrfField() ?>
<label><?= __('auth.username') ?><input type="text" name="username" required></label>
<label><?= __('auth.password') ?><input type="password" name="password" required></label>
<button type="submit" name="login" class="btn btn-primary"><?= __('login.btn_login') ?></button>
</form>
<?php else: ?>
<form method="post" action="" class="auth-form">
<?= csrfField() ?>
<label><?= __('auth.username') ?><input type="text" name="username" placeholder="<?= __('login.username_placeholder') ?>" required></label>
<label><?= __('login.label_email') ?> *<input type="email" name="email" placeholder="<?= __('login.email_placeholder') ?>" required></label>
<div class="captcha-box">
<img src="captcha.php" alt="CAPTCHA" class="captcha-img" onclick="this.src='captcha.php?'+Date.now()" title="<?= __('login.captcha_hint') ?>">
<label><?= __('login.label_captcha') ?><input type="text" name="captcha" maxlength="4" autocomplete="off" placeholder="<?= __('login.captcha_placeholder') ?>" required></label>
</div>
<label><?= __('auth.password') ?><input type="password" name="password" placeholder="<?= __('login.pwd_placeholder') ?>" required></label>
<label><?= __('auth.confirm_password') ?><input type="password" name="password2" required></label>
<label><?= __('login.label_invite') ?><input type="text" name="invite_code" placeholder="<?= __('login.invite_placeholder') ?>" value="<?= h($invite) ?>"></label>
<button type="submit" name="register" class="btn btn-primary"><?= __('login.btn_register') ?></button>
<p class="form-tip"><?= __('login.register_tip') ?></p>
</form>
<?php endif; ?>
</div>
</section>
<?php require 'includes/footer.php'; ?>