在Web开发的世界里,HTTP协议和Cookie是非常重要的概念。它们在实现用户登录状态管理等功能中扮演着关键角色。今天,我们就结合代码和笔记,详细探讨HTTP协议和Cookie存储状态的相关知识。
前端存储与后端存储概述
在开始深入探讨HTTP协议和Cookie之前,我们先来了解一下前端和后端的存储方式。前端存储主要有localStorage
、sessionStorage
、cookie
和indexDB
。localStorage
用于永久存储,容量约为5M;sessionStorage
是会话存储,同样有5M的容量;cookie
容量较小,只有4k,且有过期时间限制,一般一个浏览器最多能存储1000个cookie
,常用于存储登录状态、购物车等信息;indexDB
也是5M容量,它是一个数据库,可用于离线存储和存储结构化数据。而后端存储则有MySQL
、NoSQL
、MingoDB
等。
HTTP协议的无状态特性
HTTP协议是Web开发中最基础的协议之一,它是一种无状态
协议。这意味着每次请求都是独立的,请求一次和请求1000次,拿到的内容都一致,服务器不会记住之前的请求信息。在HTTP 0.9版本中,协议甚至没有身份的概念。直到HTTP 1.0正式版,引入了请求头(header)的概念,通过在请求头中添加一些信息,如Content-Type
、Authorization
、Cookie
等,来实现一些额外的功能。例如,当用户发送请求时,可以在请求头中带上Cookie
信息,服务器端通过解析这个Cookie
来识别用户身份。
基于Cookie的用户登录状态管理
前端代码实现
我们先来看前端的代码实现,主要涉及index.html
和script.js
文件。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Storage</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>Cookie</h1>
<div id="app">
<!-- 是否已经登录?Cookie?检查 -->
<section id="loginSection">
<form id="loginForm">
<input type="text" id="username" placeholder="Username" required>
<input type="password" id="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
</section>
<section id="welcomeSection" style="display: none;">
<p>Welcome,<span id="userDisplay"></span></p>
<button id="logoutBtn">Logout</button>
</section>
<button id="loginBtn">Login</button>
</div>
<script src="/script.js"></script>
</body>
</html>
在这个HTML文件中,我们定义了一个登录表单和一个欢迎页面。登录表单包含用户名和密码输入框,以及登录按钮。欢迎页面默认是隐藏的,当用户登录成功后会显示出来。
script.js
const loginForm = document.getElementById('loginForm');
loginForm.addEventListener('submit', async function(event) {
event.preventDefault();
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value.trim();
try{
const response = await fetch('/login',{
method:'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({username,password})
})
const data = await response.json();
console.log(data);
}catch(error){
console.log("登录出错了")
}
})
document.addEventListener('DOMContentLoaded',async()=>{
try{
const response = await fetch('/check-login');
const data = await response.json();
if (data.loggedIn) {
document.getElementById('loginSection').style.display = 'none';
document.getElementById('welcomeSection').style.display = 'block';
document.getElementById('userDisplay').textContent = data.username;
} else {
document.getElementById('loginSection').style.display = 'block';
document.getElementById('welcomeSection').style.display = 'none';
}
}catch(error){
console.log("登录出错了")
}
})
在script.js
文件中,我们为登录表单添加了提交事件监听器。当用户点击登录按钮时,会阻止表单的默认提交行为,然后收集用户名和密码,并使用fetch
API向服务器发送POST请求。同时,在页面加载完成后,会向服务器发送一个检查登录状态的请求,如果用户已经登录,则显示欢迎页面,否则显示登录表单。
后端代码实现
后端代码主要在server.js
文件中实现。
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer((req,res)=>{
if(req.method === 'GET' && req.url === '/'){
fs.readFile(path.join(__dirname,'public','index.html'),
(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/html'})
res.end(content)
})
}
if(req.method === 'GET' && req.url === '/style.css'){
fs.readFile(path.join(__dirname,'public','style.css'),
(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/css'})
res.end(content)
})
return;
}
if(req.method === 'GET' && req.url === '/script.js'){
fs.readFile(path.join(__dirname,'public','script.js'),
(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/javascript'})
res.end(content)
})
return;
}
if(req.method === 'POST' && req.url === '/login'){
res.writeHead(200,{
'Set-Cookie':'user=admin;',
'Content-Type':'application/json'
})
res.end(JSON.stringify({
success:true,
msg:'登录成功'
}))
}
if(req.method === 'GET' && req.url === '/check-login'){
if(req.headers.cookie){
res.writeHead(200,{
'Content-Type':'application/json'
})
res.end(JSON.stringify({
loggedIn:true,
username:'admin'
}))
}else{
res.writeHead(200,{
'Content-Type':'application/json'
})
res.end(JSON.stringify({
loggedIn:false,
username:''
}))
}
}
})
server.listen(8080);
在server.js
文件中,我们创建了一个HTTP服务器。当接收到不同的请求时,会根据请求的方法和URL进行不同的处理。例如,当接收到GET请求且URL为/
时,会读取并返回index.html
文件;当接收到POST请求且URL为/login
时,会进行用户名和密码的校验(这里只是简单模拟),并在响应头中设置Set-Cookie
字段,将用户信息存储在Cookie
中,同时返回登录成功的JSON数据;当接收到GET请求且URL为/check-login
时,会检查请求头中是否包含Cookie
信息,如果包含则认为用户已经登录,返回登录成功的JSON数据,否则返回未登录的JSON数据。
前后端联调过程
前后端联调是实现用户登录状态管理的关键步骤。前端通过表单收集用户输入的用户名和密码,然后使用fetch
API向服务器发送POST请求。服务器接收到请求后,进行用户名和密码的校验,通过后在响应头中设置Set-Cookie
字段,将用户信息存储在Cookie
中,并返回登录成功的JSON数据。前端接收到响应后,根据返回的数据更新页面显示。同时,在页面加载完成后,前端会向服务器发送一个检查登录状态的请求,服务器根据请求头中的Cookie
信息判断用户是否已经登录,并返回相应的JSON数据,前端再根据返回的数据更新页面显示。
另一个退出方式
易知,cookie是主流验证用户登录状态之一的方式,那我们就可以实现以下退出登录方式:
- 找到应用的Cookie并删除
- 刷新页面成功退出
总结
通过以上的代码和分析,我们深入了解了HTTP协议的无状态特性,以及如何使用Cookie
来实现用户登录状态的管理。在实际开发中,我们可以根据具体需求对代码进行扩展和优化,例如增加更多的用户信息存储、设置Cookie
的过期时间等。希望本文能帮助你更好地理解HTTP协议和Cookie
存储状态的相关知识。