fix: pure PHP login — login.php POSTs to PHP, bridge.php writes token to sessionStorage, zero JS dependency for auth

This commit is contained in:
2026-06-01 09:22:24 +00:00
parent dbe945080d
commit 69673685d9
3 changed files with 147 additions and 2 deletions
+121
View File
@@ -0,0 +1,121 @@
<?php
// Pure PHP login — no JavaScript required for authentication
session_name('jarvis_main');
session_start();
$error = '';
// Already logged in — redirect straight to app
if (!empty($_SESSION['jarvis_token'])) {
header('Location: /');
exit;
}
// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
if ($username && $password) {
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=jarvis_db;charset=utf8mb4',
'jarvis_user',
'J4rv1s_Pr0t0c0l_2026!',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? LIMIT 1');
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password_hash'])) {
$token = bin2hex(random_bytes(32));
$_SESSION['jarvis_token'] = $token;
$_SESSION['jarvis_user_id'] = $user['id'];
$_SESSION['jarvis_name'] = $user['display_name'];
$pdo->prepare('UPDATE users SET last_seen = NOW() WHERE id = ?')->execute([$user['id']]);
// Cookie lets index.html JS pick up the token and put it in sessionStorage
setcookie('j_tk', $token, 0, '/', '', true, false);
header('Location: /bridge.php');
exit;
} else {
$error = 'ACCESS DENIED';
}
} catch (Exception $e) {
$error = 'DATABASE ERROR';
}
} else {
$error = 'ENTER CREDENTIALS';
}
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>JARVIS — Authentication</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=Share+Tech+Mono&display=swap" rel="stylesheet"/>
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--bg:#000810;--cyan:#00d4ff;--cyan2:#00a8cc;--orange:#ff6600;--red:#ff2244;
--dim:rgba(0,212,255,0.4);--text:#c8e6ff;--text-dim:rgba(200,230,255,0.5);
--panel-border:rgba(0,212,255,0.2);--grid:rgba(0,180,255,0.07);--r:8px;
}
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);color:var(--text);font-family:'Share Tech Mono',monospace}
body::before{content:'';position:fixed;inset:0;background-image:linear-gradient(var(--grid) 1px,transparent 1px),linear-gradient(90deg,var(--grid) 1px,transparent 1px);background-size:40px 40px;z-index:0;pointer-events:none}
body::after{content:'';position:fixed;inset:0;background:radial-gradient(ellipse at 50% 50%,rgba(0,80,160,0.08) 0%,transparent 70%);z-index:0;pointer-events:none}
.scanlines{position:fixed;inset:0;z-index:1;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,0.03) 2px,rgba(0,0,0,0.03) 4px);animation:scanMove 8s linear infinite}
@keyframes scanMove{0%{background-position:0 0}100%{background-position:0 100%}}
#screen{position:fixed;inset:0;z-index:10;display:flex;align-items:center;justify-content:center;flex-direction:column;background:var(--bg)}
.reactor{width:160px;height:160px;position:relative;margin-bottom:40px}
.reactor .ring{position:absolute;border-radius:50%;border:2px solid var(--cyan);top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 0 8px var(--cyan),inset 0 0 8px rgba(0,212,255,0.1);animation:spinRing var(--spd,4s) linear infinite}
.reactor .r1{width:160px;height:160px;--spd:8s;border-color:rgba(0,212,255,0.3)}
.reactor .r2{width:130px;height:130px;--spd:6s;animation-direction:reverse}
.reactor .r3{width:100px;height:100px;--spd:4s;border-color:var(--orange);box-shadow:0 0 12px var(--orange)}
.reactor .r4{width:70px;height:70px;--spd:3s;animation-direction:reverse}
.reactor .core{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border-radius:50%;background:radial-gradient(circle,#fff 0%,var(--cyan) 40%,var(--cyan2) 70%,transparent 100%);box-shadow:0 0 20px var(--cyan),0 0 40px var(--cyan),0 0 80px rgba(0,212,255,0.3);animation:corePulse 2s ease-in-out infinite}
.reactor .ticks{position:absolute;inset:0;border-radius:50%}
.reactor .ticks::before,.reactor .ticks::after{content:'';position:absolute;background:var(--cyan);opacity:0.5}
.reactor .ticks::before{left:50%;top:0;width:1px;height:12px;transform:translateX(-50%)}
.reactor .ticks::after{left:0;top:50%;height:1px;width:12px;transform:translateY(-50%)}
@keyframes spinRing{from{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(360deg)}}
@keyframes corePulse{0%,100%{opacity:0.8;transform:translate(-50%,-50%) scale(1)}50%{opacity:1;transform:translate(-50%,-50%) scale(1.1)}}
h1{font-family:'Orbitron',monospace;font-size:2.5rem;font-weight:900;letter-spacing:8px;color:var(--cyan);text-shadow:0 0 20px var(--cyan),0 0 40px rgba(0,212,255,0.4);margin-bottom:8px}
p.sub{color:var(--text-dim);font-size:0.85rem;letter-spacing:4px;text-transform:uppercase;margin-bottom:40px}
form{display:flex;flex-direction:column;gap:14px;width:320px}
input{background:rgba(0,212,255,0.05);border:1px solid var(--panel-border);border-radius:var(--r);padding:12px 16px;color:var(--cyan);font-family:'Share Tech Mono',monospace;font-size:0.95rem;outline:none;transition:border-color .2s,box-shadow .2s;letter-spacing:1px;width:100%}
input:focus{border-color:var(--cyan);box-shadow:0 0 12px rgba(0,212,255,0.2)}
input::placeholder{color:var(--dim);letter-spacing:1px}
button{background:linear-gradient(135deg,rgba(0,212,255,0.15),rgba(0,212,255,0.05));border:1px solid var(--cyan);border-radius:var(--r);padding:14px;color:var(--cyan);font-family:'Orbitron',monospace;font-size:0.8rem;font-weight:700;letter-spacing:3px;text-transform:uppercase;cursor:pointer;transition:all .2s;box-shadow:0 0 12px rgba(0,212,255,0.1)}
button:hover{background:rgba(0,212,255,0.2);box-shadow:0 0 20px rgba(0,212,255,0.3)}
.err{color:var(--red);font-size:0.85rem;text-align:center;letter-spacing:1px;min-height:20px}
</style>
</head>
<body>
<div class="scanlines"></div>
<div id="screen">
<div class="reactor">
<div class="ring r1"></div><div class="ring r2"></div>
<div class="ring r3"></div><div class="ring r4"></div>
<div class="core"></div><div class="ticks"></div>
</div>
<h1>JARVIS</h1>
<p class="sub">Just A Rather Very Intelligent System</p>
<form method="POST" action="/login.php">
<input type="text" name="username" placeholder="IDENTIFICATION" autocomplete="username" value="myron"/>
<input type="password" name="password" placeholder="ACCESS CODE" autocomplete="current-password"/>
<button type="submit">INITIALIZE SYSTEM</button>
<?php if ($error): ?>
<div class="err"><?= htmlspecialchars($error) ?></div>
<?php else: ?>
<div class="err"></div>
<?php endif; ?>
</form>
</div>
</body>
</html>