前言
http 协议的特点
一、http 协议特点
支持客户/服务器模式
由(只能由)客户端向服务器发出请求,服务器端响应请求,并进行相应的服务;
服务器端如果没有接收到请求,是不会向客户端发出响应的。
简单,快速
- 请求方法少,常用的有GET,HEAD,POST等。每种方法规定了客户与服务器联系的类型不同
- HTTP 协议简单,所以,HTTP 服务器的程序规模小,通信快
灵活
- http允许传输任意类型的数据对象
- 使用Content-Type 来标记传输的类型。
参考
https://www.runoob.com/http/http-content-type.html
查看Content-type
无连接
无连接强调的是http 的特性;
特点:限制每次连接只处理一个请求
http 协议的长连接和短连接,实质上是TCP 协议的长连接和短连接
实现方式:
短连接;由客户端发起
长连接;TCP长连接的保活功能主要为服务器应用提供
短连接
短连接可以理解成是http 连接的实现,
服务器处理完用户的请求,并收到客户的应答后,就会断开连接
优点:
- 节省传输时间,实现简单
长连接
当HTTP协议头部中字段Connection:keep-alive表示支持长链接。
优点:
- 长连接专门解决效率问题。当建立好了一个连接之后,可以多次请求。
缺点:
- 容易造成占用资源不释放的问题。
有效性,有效性,没断开,可以使用长连接;
无状态
HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。
换句话说,就是每次连接,都要把需要的信息都携带上,不记录之前的信息;
如果携带的信息大,那么处理起来,就慢;如果携带的信息少,那么处理起来就快。
为了解决无状态的问题,使用
- Cookie
- Session
来解决
二、URL与URI的区别与联系
三、报文结构分析
通用报文头
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主题的传输编码方式 |
Upgrade | 升级为其他协议 |
Vim | 代理服务器的相关信息 |
Warning | 错误通知 |
Connection
Connection:keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
Connection:close 代表-个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,当客户端再次发送Request,需要重新建立TCP连接
请求报文头
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Acccpt-Language | 优先的语言(自然语言) |
Authorization | Wcb认证信息 |
Expeet | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
1f-Modified-Simce | 比较资源的更新时间 |
If-None-Mateh | 比较实体标记(与If-Match相反) |
lf-Range | 资源未更新时发送实体Byte的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modifed-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP客户端程序的信息 |
User-Agent
作用: 告诉HTTP服务器, 客户湍使用的操作系统和浏览器的名称和版本
很多情况下我们会通过User-Acnet来判断浏览器类型,从而进行不同的兼容设计
响应报文头
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体报文头
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
Content-type
作用: 说明了报文体内对象的媒体类型
- text/html:HTML格式
- text/plain :纯文本格式
- text/xml:XML格式
- image/gif:gif图片格式
- image/jpeg:jpg图片格式
- image/png:png图片格式
application
- application/xhtml+xml:XHTML格式
- application/xml:XML数据格式
- application/atom+xml: Atm XML聚合格式
- application/json据格式
- JSON类application/pdf:pdf格武
- application/msword:Word文档格式
- application/octet-stream :二进制流数据(如常见的文件下载)
- application/x-www-form-urencoded:表单提交
四、发起http请求
发送请求的方法
方法名称 | 方法说明 | 支持的HTTP 协议版本 |
---|---|---|
get | GET 方法用于根据 URI 参数从服务器中获取数据,是最常用的请求方法之一 | 1.0、1.1 |
head | HEAD 方法与 GET 方法类似,但服务器在响应时只返回响应行和响应头,不会返回响应体 | 1.0、1.1 |
post | POST 请求用于将数据发送到服务器。例如使用 HTML 表单上传文件或提交客户信息等 | 1.0、1.1 |
put | PUT 方法可以向服务器中写入文档,有点类似于使用 FTP 上传文件 | 1.0、1.1 |
delete | DELETE 方法用于删除 URI 所指定的目标资源,与 PUT 方法正好相反 | 1.0、1.1 |
connect | CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信 | 1.1 |
options | OPTIONS 方法用来查询目标资源所在服务器支持的 HTTP 方法 | 1.1 |
trace | TRACE 方法可以让服务器端将收到的请求返回给客户端,主要用于开发阶段的测试和诊断 | 1.1 |
link | 建立和资源之间的联系 | 1.0 |
unlink | 断开链接关系 | 1.0 |
http 状态码
- 1xx:指示信息-表示请求已接收,继续处理;这类响应是临时响应
- 2xx:成功-表示请求已被成功接收
- 3xx:重定向-要完成请求必须进行更进一步的操作
- 4xx:客户端错误-请求有语法错误或请求无法实现
- 5xx:服务器错误-服务器未能实现合法的请求
比如: - 200 OK:客户端请求成功
- 202 Accepted 已接受,但是未处理成功
- 206 Partial Content:客户发送了一个带有Range头的GET请求,服务器完成了它
- 301 Moved Permanently:所请求的页面已经转移至新的url;永久移动。浏览器会自动定向到新的URI.
- 302 Found:所请求的页面已经临时转移至新的url
- 304 Not Modified:客户端有缓冲的文档并发出了一个条件性的请求,服务器告诉客户原来缓冲的文档还可以继续使用
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized:请求未经授权,这个状态代码必须和WW-Authenticate报头域一起使用
- 403 Forbidden:对被请求页面的访问被禁止
- 404 Not Found:请求资源不存在
- 500 Internal Server Error:服务器发生不可预期的错误原来缓冲的文档还可以继续使用
- 502 Bad Gateway 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
- 503 Server Unavailable:请求未完成,服务器临时过载或当机,一段时间后可能恢复正常
get 和post 的区别
其实get 和post 没有本质的差别;
两者只是请求方法不一样;
get 请求浏览器里面带不了请求体;在nodejs 里面可以携带请求体。
post 请求在浏览器里面可以带请求体
所以在浏览器中,get 和post 的区别:
- GET 通过url 传递参数,POST 可以通过url 和request body 传递参数;
- GET 传递的参数上限是2k;POST 没有限制
- GET在浏览器回退时是无害的,而POST会再次提交请求
- GET产生的URL地址可以被收藏,而POST不可以
- GET请求会被浏览器主动缓存,而POST不会,除非手动设置
- GET请求只能进行url编码,而POST支持多种编码方式
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
- GET请求在URL中传送的参数是有长度限制的,而POST没有限制
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
post 两次请求
当发送post时,有时候,有发现有options请求;有options 一共有两种情况:
当请求头是application/json 的形式的时候:
1.跨域;
2. 自定义请求头的时候也会发送;
当发送跨域的POST请求时,浏览器会先发送一次OPTIONS请求,这是因为浏览器的同源策略。OPTIONS请求被称为预检请求(pre-flightrequest),它是CORS(跨源资源共享)机制中的一部分。
预检请求的目的是为了确保实际请求(例如POST、PUT等)对目标服务器是安全的。在实际请求之前,浏览器向服务器发送一个预检请求,询问服务器是否允许跨域请求以及允许哪些HTTP方法、头部字段等。服务器通过响应头信息告诉浏览器它支持哪些方法和头部字段。
OPTIONS请求会包含以下头部信息:
0zigin’:表示请求来源的域名
表示实际请求将使用的HTTP方法。Access-Control-Request-Method: 表示实际请求将携带哪些自定义头部字段。Access-Control-Request-Headers
:
服务器需要在响应头中返回一些CORS相关的信息,例如:
表示哪些域名可以进行跨域访问Access-Control-Allow-0rigin
表示允许哪些HTTP方法。Access-Control-Allow-Methods:
表示允许哪些头部字段。Access-Control-Allow-Headers`:
如果服务器允许当前请求的跨域访问,那么浏览器才会发起实际的POST请求。否则,浏览器将阻止请求,并在控制台报告错误。
五、解决无状态
Cookie
-
cookie 保存在客户端;客户端请求服务器,如果服务器需要记录用户的状态,就会返回一段文本信息给客户端浏览器。浏览器接收到信息后,就会保存起来。在下次请求的时候,浏览器把请求的信息连同服务器发送过来的cookie一起传送给服务器。服务器通过解析cookie 来辨认用户的状态。
-
不能跨域。两个网址只要域名,端口都相同,就可以共享cookie。不要求协议相同。
-
cookie 大小有限制,大多数浏览器最大支持4096字节。最大支持300个,主流浏览器FirFox :50个,Opera:30个。如果超出了个数显示,浏览器会随机清除cookie,给新cookie腾位置。
-
明文保存,不适合保存重要或者涉及隐私的内容
-
只能存储String 类型的对象
-
有过期时间,一旦过期,浏览器会自动删除
可以在控制台打出
console.log(document.cookie)
查看此网站的cookie
查看cookie 是否可用
console.log(window.navigator.cookieEnabled);//true
cookie 的格式
Set-Cookie: “name=value;domain=.domain.com;path=/;expires=Sat, 05 Jun 2024 13:29:01 GMT;HttpOnly;secure”
name:一个唯一确定的cookie名称。通常来讲cookie的名称是不区分大小写的。
value:存储在cookie中的字符串值。最好为cookie的name和value进行url编码
domain:cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:yq.aliyun.com),也可以不包含它(如:.aliyun.com,则对于aliyun.com的所有子域都有效).
path: 表示这个cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送cookie。
expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。
max-age: Cookie 失效的时间,单位秒,默认为 -1。如果为正数,则该 Cookie 在 maxAge 秒后失效。如果为负数,该 Cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 Cookie 。与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒),而不是一个固定的时间点。正常情况下,max-age的优先级高于expires。
HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。如果给某个 Cookie 设置了HttpOnly属性,则无法通过 JS 脚本 读取到该Cookie 的信息,但还是能通过 Application 中手动修改 Cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全。
secure: 安全标志 设置Cookie是否使用安全协议传输。安全协议有 HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。当 secure 值为 true 时,Cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
Application 修改利用cookide 可以做自动登录,保存浏览历史,身份验证等功能。
js 处理cookie
// 读取cookie
function getCookie(name) {
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg))
return (arr[2]);
else
return null;
}
// 设置cookie
/*
name:cookie 名
value: cookie 值
expiredays: 有效时间
*/
function setCookie (name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = name+ "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
};
// 单个设置
//document.cookie='name=123;expires=Thu, 25 Nov 2024 12:31:23 GMT'
// 删除cookie
function delCookie (name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null)
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
};
服务端nodejs
设置cookie
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res) {
res.setHeader('status', '200 OK');
res.setHeader('Set-Cookie', 'uid=123456;domain=.xxx.com;path=/;max-age=1000');
res.write('Hello World');
res.end();
}).listen(8888);
console.log('running localhost:8002')
服务器解析cookie
因为客户端传过来的cookie 值会有重复项,所以只取第一个匹配的即可。
var parse = function(cstr) {
if (!cstr) {
return null;
}
var dec = decodeURIComponent;
var cookies = {};
var parts = cstr.split(/\s*;\s*/g);
parts.forEach(function(p){
var pos = p.indexOf('=');
// name 与value存入cookie之前,必须经过编码
var name = pos > -1 ? dec(p.substr(0, pos)) : p;
var val = pos > -1 ? dec(p.substr(pos + 1)) : null;
//只需要拿到最匹配的那个
if (!cookies.hasOwnProperty(name)) {
cookies[name] = val;
}/* else if (!cookies[name] instanceof Array) {
cookies[name] = [cookies[name]].push(val);
} else {
cookies[name].push(val);
}*/
});
return cookies;
}
cookie 的认证流程
nodejs使用第三方插件测试写入
/*
* @Author:
* @Date: 2024-02-02 18:40:28
* @LastEditors:
* @LastEditTime: 2024-02-05 16:01:01
* @FilePath: \vite-vue3-electron\server\index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const express=require('express');
const app =express();
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')
//设置跨域访问
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
app.use(bodyParser.urlencoded({ extended: false }))// 解析字符
app.use(bodyParser.json())
app.use(cookieParser('aabbccdd'))
var questions=[
{
data:213,
num:444,
age:12
},
{
data:456,
num:678,
age:13
}];
app.get('/getData',function(req,res){
console.log("req",req)
// res.status(200),
// res.json(questions)
let response={
status:200,
data:questions
}
res.send(response);
});
app.post('/postData',(req,res)=>{
console.log(req.body);//获取前端ajax提交的数据
res.send({
code:200,
data:req.body
})
})
// 设置cookie
app.get('/cookie',(req,res)=>{
// 使用了中间件后就可以访问req和res上的cookies对象
console.log(req.cookies);
// 不加密写入cookie
// res.cookie('num', 10, {
// // domain: 'xxx.com',
// // path: '/',
// maxAge: 24 * 3600 * 1000
// })
// 加密后读取cookie
console.log(req.signedCookies['num'])
res.cookie('num', 10, {
// httpOnly: true,
// secure: true,
signed: true,// 签名一定要写上这个,表示对cookie 进行前民
maxAge: 24 * 3600 * 1000
})
res.send({
code:200,
data:'ok'
});
})
//配置服务端口
var server = app.listen(8001, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
})
如果cookie 不加签名的话
如果加了签名
cookie 的优缺点
优点
优点 | 备注 |
---|---|
扩展性强,简单易用 | 是一个文本信息,键值对的方式保存 |
可用性高 | 客户端,服务器端都能使用 |
占用内存少 | 存储在客户端,不会给服务器端造成数据压力 |
具有持久性 | 通过设置max-age;可以在客户端上保存长达数年的时间;轻松保存用户的信息。即使服务端崩溃,cookie 的值夜不会收到影响 |
具有透明性 | 可以在Application 上清晰的看到cookie |
缺点
缺点 备注 | |
---|---|
明文暴露问题 | 很容易被用户看到,并窃取 |
安全性问题 | 在application,明文暴露 |
大小数量限制 | 大小4096字节,数量一般是50个 |
禁用限制 | 浏览器使用无痕模式,禁用cookie 存储 |
跨域问题 | 只能是ip,端口都相同才能共用cookie |
使用场景
- 用户登录状态
- 用户信息存储
- 跟踪用户行为
- 广告定位
- 用户行为偏好
- 缓存数据,用户历史和浏览数据
使用场景举例
前提:. 服务端返回的cookie 不需要客户端去关心。下面的session 有图示证明这个说法。所以客户端只需要关心自己设置的cookie 值就好。
cookie 失效:
- cookie未设置持久化,浏览器关闭,那么cookie 就会立刻失效。
- 服务端修改cookie 信息,另cookie 值失效。
用户7天免登录
// 保存用户信息
function setCookie(name,pwd,cookieName) {
let userName = name // 用户名
let passWord = pwd //密码
let cookieName = cookieName // cookie名称
let data = {
username: userName,
password: passWord
}
let d = new Date()
let saveTime = 7// cookie保存时间(单位:天)
d.setDate(d.getDate() + saveTime)
document.cookie = cookieName + '=' + JSON.stringify(data) + ';path=/;expires=' + d.toGMTString()
}
// 验证cookie 是否失效
function getCookie(cookieName) {
let cookie = document.cookie
let cookieName = cookieName // cookie名称
let arr = cookie.split('; ') // 将cookie信息和时间戳拆分为数组
let userInfo = null
for (let i = 0; i < arr.length; i++) {
let tempArr = arr[i].split('=') // 将cookie名称和data拆分开,分别是数组的第一个元素和第二个元素
if (tempArr[0] === cookieName) {
userInfo = JSON.parse(tempArr[1])
}
}
if (userInfo) {
// cookie存在,直接登录
console.log(userInfo)
} else {
// 因为cookie不存在,所以不做任何处理
}
}
Session
session 是记录客户端状态的字段,保存在服务器上。
特点 | 说明 |
---|---|
基于cookie 实现,由服务器实现,且存储在服务器端 | 不会暴露给客户端,客户端只能拿到Session id |
易用性 | 可以存储任意类型的数据 |
独立性,会话隔离 | 每个客户端与服务器之间建立联系的时候,都有唯一的session ID |
临时性 | 有过期时间 |
状态保持 | 将信息存储在session 中,可以获取用户的信息状态 |
可灵活配置 | 可以存放多种信息,如用户登录状态 |
nodejs 设置session
/*
* @Author: @@@ 1094549944@qq.com
* @Date: 2024-02-02 18:40:28
* @LastEditors: @@@ 1094549944@qq.com
* @LastEditTime: 2024-02-05 16:29:47
* @FilePath: \vite-vue3-electron\server\index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const express=require('express');
const app =express();
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')
var session = require('express-session');
//设置跨域访问
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
app.use(bodyParser.urlencoded({ extended: false }))// 解析字符
app.use(bodyParser.json())
app.use(cookieParser('aabbccdd'))
app.use(session({
name: 'session_name', // 这里是cookie的name,默认是connect.sid
secret: 'aaabbbccc', // 建议使用 128 个字符的随机字符串
resave: true,
saveUninitialized: false,
cookie: { maxAge: 60 * 1000, httpOnly: true }
}));
var questions=[
{
data:213,
num:444,
age:12
},
{
data:456,
num:678,
age:13
}];
app.get('/getData',function(req,res){
console.log("req",req)
// res.status(200),
// res.json(questions)
let response={
status:200,
data:questions
}
res.send(response);
});
app.post('/postData',(req,res)=>{
console.log(req.body);//获取前端ajax提交的数据
res.send({
code:200,
data:req.body
})
})
// 设置cookie
app.get('/cookie',(req,res)=>{
// 使用了中间件后就可以访问req和res上的cookies对象
console.log(req.cookies);
// 不加密写入cookie
// res.cookie('num', 10, {
// // domain: 'xxx.com',
// // path: '/',
// maxAge: 24 * 3600 * 1000
// })
// 加密后读取cookie
console.log(req.signedCookies['num'])
res.cookie('num', 10, {
// httpOnly: true,
// secure: true,
signed: true,// 签名一定要写上这个,表示对cookie 进行前民
maxAge: 24 * 3600 * 1000
})
res.send({
code:200,
data:'ok'
});
})
// 设置session
app.get('/session',(req,res)=>{
console.log(req.cookies);
console.log("req.session.sessionNum || req.cookies.sessionNum",req.session.sessionNum || req.cookies.sessionNum)
if(req.session.sessionNum || req.cookies.sessionNum) {
res.send({
code:200,
data:'ok'
});
} else {
req.session.sessionNum = 1;
res.cookie('sessionNum', 1, { maxAge: 60 * 1000, singed: true});
res.send({
code:200,
data:'first'
});
}
})
//配置服务端口
var server = app.listen(8001, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
})
第二次访问
此时浏览器请求
第一次,在返回头有set-cookie
第二次请求 在请求头,携带cookie
session 认证流程
注意:不管是session 还是cookie, 都不需要客户端做什么。都是服务端的操作。
保存Session ID 的方式
- Cookie
- URL 重写
- 隐藏表单
URL 重写
如果浏览器禁止cookie,比如说,浏览器在无痕模式下运行,是禁止写入cookie 的,可以采用url 重写的方式,直接在url上写入sessionId
方式有两种
- http://www.baidu.com;sessionId=1234567123131xxx
- http://www.baidu.com?sessionId=1234567123131xxx
两者没有区别,只是在解析中,处理方式有所区别。第一种可以把sessionid 和其他的params 区分开
Session 超时失效
Session的有效期
Session超时失效
程序调用HttpSession.invalidate()
服务器进程被停止
session 的优缺点
优点 | 说明 |
---|---|
比Cookie 安全一点 | |
可以存储任意类型的数据 | |
支持集群部署 | |
具有唯一性 | |
相较于JWT,具有自动清除机制 | 服务器会有session 回收机制,可以自动删除过期的Session |
兼容性好 |
缺点 | 说明 |
---|---|
过度依赖Cookie | 如果用户禁用cookie,那么就会非常影响用户体验 |
占用服务器资源 | 存储在服务器端 |
生命周期问题 | session过期问题;解决办法:使用定时器刷新session,或者将session 的过期时间设置的更长一些,确保session 不会过早失效 |
分布式问题 | 解决办法:1. 从存储角度:使用集中式session 存储方案,比如使用redis等缓存中间件来缓存session 信息;2. 使用Nginx;。以 Nginx 为例,可以配置 ip_hash 来实现 可以让相同 IP 的请求在负载均衡时都打到同一台机器上 |
安全问题 | 解决办法:可以使用加密技术;比如使用https协议 |
总结
本篇文章表格主要参考 慕课网的《大话HTTP协议 漫画+图解打造的编程基础课程》
参考文档:
https://blog.csdn.net/qq_41895003/article/details/130448214
https://blog.csdn.net/qq_41895003/article/details/130455766