HTTP协议是无状态的
什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的
Cookie
概念
cookie是服务端发送给客户端的并保存在客户端(浏览器)的数据块,这个数据块通常用来识别用户身份,保持会话状态,保存服务端与用户之间交互的数据。
在http协议中的操作流程
1.客户端向服务端发送请求
2.服务器给出响应,响应内容请求头中包括set-cookie的数据,这个数据中存储的就是cookie信息
3.客户端再向服务端发送请求,携带对应的cookie信息
4.服务端给出响应
cookie常见参数设置
value
cookie中存储的值,通常是字符串数据
expires/max-age
预计cookie被删除的时间,如果两个参数都没有设置,在浏览器关闭时cookie将被删除;如果设置了max-age ,expires将失效
secure
标记该Cookie只能通过安全的HTTPS连接被发送到服务器。如果设置了Secure,Cookie在HTTP上不会被发送,有助于保护数据免遭窃听。
cookie的作用
1.验证用户身份信息
2.保持用户会话状态
3.服务端与客户端交互数据的保存。
Session
session的概念
Session是一种在服务器上保存用户数据的方法,用于跨多个页面请求或访问中保持用户状态或数据。与Cookie主要在客户端保存数据不同,Session数据主要存储在服务器端。每个用户都可以获得一个唯一的会话ID,用于区分不同的用户。这个会话ID通常通过Cookie发送给用户的浏览器,但也可以通过URL重写等其他方式传递。
session 翻译过来就是『会话』。用户打开一个浏览器, 点击多个超链接, 访问服务器多个web资源, 然后关闭浏览器, 整个过程称之为一个会话。
session流程
1.客户端向服务器发送http请求
2.服务端生成session对象,将sessoinId 设置在请求头中的set-cookie(key为JsessionId)字段中,发送给客户端
3.客户端再次发送请求时将sessionId存储于cookie,发送给服务端
4.服务端给出响应
session的特点
- session 是另一种记录服务器和客户端会话状态的机制;
- session 存储在服务器端,一般是文件中,也可以存在数据库或缓存中。
- session 一般基于 cookie 实现。session 中包含敏感信息存储在服务器端,通常将 sessionId 存储在客户端的 cookie 中,客户端每次请求携带 sessionId 即可识别用户。
session的作用
Session在Web应用中起着至关重要的作用,主要用于跨多个页面请求或用户访问中维持用户的状态和数据。以下是Session的一些主要作用和优点:
### 1. 用户认证和管理状态
- **保持登录状态**:最常见的Session用途之一是跟踪用户的登录状态。用户登录后,服务器创建一个Session,并将用户信息存储在该Session中。只要Session有效,用户就无需在每个页面请求时重新登录。
- **存储用户特定数据**:Session可以存储用户偏好设置、角色权限等信息,使得服务器能够根据用户的不同特征提供个性化的内容和服务。### 2. 跨页面共享数据
- **临时数据传递**:Session允许在用户浏览网站的不同页面之间共享数据,例如,在多步骤表单提交过程中暂存用户的输入数据,直到整个流程完成。
### 3. 购物车功能
- **跟踪购物车内容**:电子商务网站中,Session用于跟踪用户添加到购物车中的商品。即使用户在没有登录的情况下浏览网站,Session也能够帮助保持购物车内容的持续性。
### 4. 安全性增强
- **防止CSRF攻击**:通过在Session中存储一个CSRF令牌(CSRF Token),并在每次表单提交时验证该令牌,可以有效防止跨站请求伪造(CSRF)攻击。
### 5. 减轻服务器负担
- **减少数据库查询**:通过在Session中存储频繁访问的数据,如用户配置信息,可以减少对数据库的查询次数,从而提高应用性能。
### 6. 支持复杂的交互逻辑
- **状态机和工作流**:Session可以作为存储状态机或工作流状态的一种手段,对于实现复杂的业务逻辑非常有用。
### 注意事项
尽管Session带来了许多优点,但在使用时也需要注意一些问题:
- **资源消耗**:每个Session都会占用服务器资源。如果网站访问量巨大,大量的Session可能会对服务器性能产生影响。
- **安全性**:Session信息通常存储在服务器上,但Session标识符(如Cookie中的会话ID)可能被拦截。因此,需要通过加密通信(如HTTPS)、HttpOnly和Secure Cookie标志等措施来保护Session的安全。
- **过期管理**:需要合理设置Session的过期时间,并清理过期的Session,以避免无用的Session数据占用过多资源。总的来说,Session是Web开发中用于维护用户状态和数据的强大工具,通过合理使用和管理,可以为用户提供安全、连贯和个性化的服务。
session和cookie的对比
- 存储方式:cookie 数据存放在客户的浏览器上,session 数据放在服务器上;
- 安全性:cookie 是本地存储,不是很安全,别人可以分析存放在本地的 cookie 并进行欺骗;
- 存储大小:很多浏览器限制单个 cookie 保存的数据不能超过4K,一个站点最多保存20个cookie,session 没有类似的限制;
- 生存周期: cookie 可设置为长时间保持,Session 一般失效时间较短,一般客户端关闭 session 就会失效
session和cookie的有效期对比
对session和cookie的理解_cookie默认有效期多长-CSDN博客
Token
什么是token?
token 是验证用户身份的凭证,我们通常叫它:
令牌
。最简单的token组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,以哈希算法压缩成一定长的十六进制字符串)。
token交互过程
1.客户端首先完成登陆认证2.服务端接受请求并进行鉴权,鉴权认证通过后将token返回给客户端,客户端收到token信息后将token存储在cookie或者localstorage中3.客户端发送请求携带token信息4.服务端对token进行验证,token验证通过后返回客户端请求的数据
什么是JWT
从本质上讲 JWT 也是一种 token,只不过 JWT 是被大家广泛接受的标准。
JWT 即:Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息。
JWT组成
header
头部主要是用来指明签名的算法,避免消息被篡改,jwt 中常用的签名算法是 HS256,常见的还有md5,sha 等,签名算法是不可逆的。声明算法的字段名为alg,同时还有一个typ的字段,默认JWT即可。以下示例中算法为HS256,
{"alg": HS256, "typ": "JWT"}
这个header中就指明了使用的算法是HS256
payload
载荷就是存放有效信息的地方。主要包含三个部分:
标准中注册的声明
;公共的声明
;私有的声明
。
JWT规定了7个官方字段,供选用
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除此之外,我们也可以定义私有的声明(主要是用户信息)
一些常见的私有声明示例包括:
role
: 用户角色username
: 用户名scope
: 授权范围
signature
签名是对头部和负载两个部分进行签名,防止数据篡改。 签名里面有个核心就是要定义一个密钥,这个密钥只有服务器能知道,然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256)
JWT相对于Cookie&Session有什么区别?
1.cookie&session机制最大的问题在于不支持横向拓展型,主要表现为:当服务端存在多台服务器,我们无法保证每次的请求都发送在同一台服务器上,那么用户信息通过session就无法验证鉴权
2.JWT是无状态的token,token信息回存储在请求头或者cookie中。
最大的缺点是 token 过期处理问题,由于服务器不保存 Session 状态,因此无法在使用过程中废止或者更改权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
3.由于JWT信息不会进行加密 所以通常不会存储敏感信息
Go语言中使用JWT实例
// JWT加密
func (l *LoginLogic) getJwtToken(secretKey, userName string, iat, seconds, userId int64) (string, error) {
claims := make(jwt.MapClaims)
//claims["exp"] = iat + seconds //过期时间 Unix时间戳格式
//claims["iat"] = iat //设定时间 Unix时间戳格式
claims["userId"] = userId
claims["userName"] = userName
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(secretKey))
}
// 生成jwt
func generateToken(user *user.UserInfo) (string, error) {
token := jwt.New(jwt.SigningMethodHS256)
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Add(tokenDuration).Unix()
claims["uid"] = user.ID
claims["iat"] = time.Now().Unix()
claims["issuer"] = "gocron"
claims["username"] = user.UserName
claims["is_admin"] = user.IsAdmin
token.Claims = claims
return token.SignedString([]byte("jasdjksdajkdja"))
}