单点登录(SSO)以及Cookie、Session和Token的区别

在这里插入图片描述

1. Cookie 和 Session

HTTP 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;Session 和 Cookie 的主要目的就是为了弥补 HTTP 的无状态特性。

1.1 Cookie是什么

Cookie,它是客户端浏览器用来保存服务端数据的一种机制。

当通过浏览器进行网页访问的时候,服务器可以把某一些状态数据以 key-value的方式写入到 Cookie 里面存储到客户端浏览器。

然后客户端下一次再访问服务器的时候,就可以携带这些状态数据发送到服务器端,服务端可以根据 Cookie 里面携带的内容来识别使用者。

Cookie 主要用于下面三个目的:

  • 会话管理:登陆、购物车、游戏得分或者服务器应该记住的其他内容
  • 个性化:用户偏好、主题或者其他设置
  • 追踪:记录和分析用户行为

主要过程可以简单用下图表示:
在这里插入图片描述
大致分为以下几步:

  1. 客户端发送请求到服务端(比如登录请求)。
  2. 服务端收到请求后生成一个 session 会话。
  3. 服务端响应客户端,并在响应头中设置 Set-Cookie。Set-Cookie 里面包含了 sessionId,它的格式如下:Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用来标识客户端的。
  4. 客户端收到该请求后,如果服务器给了 Set-Cookie,那么下次浏览器就会在请求头中自动携带 cookie。
  5. 客户端发送其它请求,自动携带了 cookie,cookie 中携带有用户信息等。
  6. 服务端接收到请求,验证 cookie 信息,比如通过 sessionId 来判断是否存在会话,存在则正常响应。

1.2 Session是什么

Session 表示一个会话,它是属于服务器端的容器对象。

默认情况下,针对每一个浏览器的请求,Servlet 容器都会分配一个 Session。

Session 本质上是一个 ConcurrentHashMap,可以存储当前会话产生的一些状态数据。

session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。

session机制采用的是在服务器端保持 HTTP 状态信息的方案。为了加速session的读取和存储,web服务器中会开辟一块内存用来保存服务器端所有的session,每个session都会有一个唯一标识sessionid,根据客户端传过来的sessionid(cookie中),找到对应的服务器端的session。为了防止服务器端的session过多导致内存溢出,web服务器默认会给每个session设置一个有效期, (30分钟)若有效期内客户端没有访问过该session,服务器就认为该客户端已离线并删除该session。

整个请求过程图,如下所示:
在这里插入图片描述

1.2.1 Session 如何判断是否是同一会话?

服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客户端发送要求设置 Cookie 的响应; 客户端收到响应后,在本机客户端设置了一个 JSESSIONID=XXXXXXX的 Cookie 信息,该 Cookie 的过期时间为浏览器会话结束;
在这里插入图片描述
接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。

1.3 Cookie与Session的在请求中的工作流程

在这里插入图片描述
(1)客户端第一次访问服务端的时候,服务端会针对这次请求创建一个会话,并生成一个唯一的 sessionID 来标注这个会话。

(2)然后服务端把这个 sessionID 写入到客户端浏览器的 cookie 里面,用来实现客户端状态的保存。

(3)在后续的请求里面,每次都会携带sessionID,服务器端就可以根据这个sessionID 来识别当前的会话状态。

所以,总的来说,Cookie 是客户端的存储机制,Session 是服务端的存储机制。

1.4 Cookie与Session存在问题

当项目的并发量越来越大的时候,我们一台服务器不够,想要有多台Tomcat来部署一个Tomcat集群时,由于Session是不能共享的,所以该场景不适用!

如果是前后端分离的项目,即前端代码和后端代码部署在不同的服务器上时,也是不可以使用Session进行登入的!

1.5 Token是什么

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

token 的组成:

token 是一串被加密后字符串,它通常使用 uid(用户唯一标识)、时间戳、签名以及一些其它参数加密而成。我们将 token 进行解密就可以拿到像 uid 这类的信息,然后通过 uid 来进行接下来的鉴权操作。

token 认证流程:

  1. 客户端发起登录请求,比如用户输入用户名和密码后登录。
  2. 服务端校验用户名和密码后,将用户 id 和一些其它信息进行加密,生成 token。
  3. 服务端将 token 响应给客户端。
  4. 客户端收到响应后将 token 存储下来。
  5. 下一次发送请求后需要将 token 携带上,比如放在请求头中或者其它地方。
  6. 服务端 token 后校验,校验通过则正常返回数据。

用图表示大致如下:
在这里插入图片描述

1.5.1 为什么要有token?

  1. Token 可以是无状态的,可以在多个服务间共享
  2. Token 可以避免 CSRF攻击(跨站点请求伪造)
  3. 减轻服务器压力。通常session是存储在内存中的,每个用户通过认证之后都会将session数据保存在服务器的内存中,而当用户量增大时,服务器的压力增大。
  4. Token完全由应用管理,避开同源策略。

1.6 Cookie和Session的区别

(1)存储位置不同

  • cookie在客户端浏览器;
  • session在服务器;

(2)存储容量不同

  • cookie<=4K,一个站点最多保留20个cookie;
  • session没有上线,出于对服务器的保护,session内不可存过多东西,并且要设置session删除机制;

(3)存储方式不同

  • cookie只能保存ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据;
  • session中能存储任何类型的数据,包括并不局限于String、integer、list、map等;

(4)隐私策略不同

  • cookie对客户端是可见的,不安全;
  • session存储在服务器上,安全;

(5)有效期不同

  • 开发可以通过设置cookie的属性,达到使cookie长期有效的效果;
  • session依赖于名为JESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session达不到长期有效的效果;

(6)跨域支持上不同

  • cookie支持跨域;
  • session不支持跨域;

1.7 Token和Session的区别

1)session是一种记录服务器和客户端会话状态的机制,使服务端有状态化。而token是令牌,访问资源接口(API时)所需要的认证资源,token使服务器无状态化,不会存储会话信息。

2)session和token并不矛盾,作为身份认证token比session安全性更好,因为每一个请求都有签名,还能防止监听以及重放攻击,而session就必须依赖链路层来确保通讯安全了。

1.8 总结

在这里插入图片描述

2. 什么是单点登录

单点登录的英文名叫做:Single Sign On(简称SSO),指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的系统。简而言之,多个系统,统一登陆。

2.1 单点登录原理

sso需要一个独立的认证中心,所有子系统都通过认证中心的登录入口进行登录,登录时带上自己的地址,子系统只接受认证中心的授权,授权通过令牌(token)实现,sso认证中心验证用户的用户名密码正确,创建全局会话和token,token作为参数发送给各个子系统,子系统拿到token,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。
在这里插入图片描述

3. JWT落地的SSO

3.1 什么是JWT

具体可参见:https://jwt.io/

JSON Web Token (JWT) 是一个开源标准(RFC 7519),它定义了一种紧凑且自完备的方法用于在各参与方之间以JSON对象传递信息。以该种方式传递的信息已经被数字签名,因而可以被验证并且被信任。它是目前最流行的跨域身份验证解决方案。它本质是token票据,在认证登录过程中表明用户的登录标识。JWT既可以使用盐(secret)(HMAC算法)进行签名,也可以使用基于RSA/ECDSA算法的公钥/秘钥对进行签名。

3.2 为什么要使用JWT?

JWT的精髓在于:“去中心化”,就是数据保存在各个客户端而不是服务器

3.3 JWT认证登录流程

在这里插入图片描述

  1. 用户直接访问资源服务器,未登录状态
  2. 资源服务器校验JWT 失败,返回未登录信息
  3. 访问登录 提交username password
  4. 登录认证服务器校验用户信息,
    1. 校验用户名是否存在
    2. 校验密码是否正确
    3. 校验其他必要条件:锁定 开启 过期等
  5. 返回JWT,其中jwt携带信息
    1. 用户名
    2. 用户id
    3. 用户权限
  6. 用户浏览器携带JWT访问资源服务器
  7. 资源服务器校验JWT
    1. 解析用户信息
    2. 解析用户权限
    3. 判断授权是否允许
  8. 数据返回
    1. 如果解析成功授权成功返回正确数据json
    2. 如果解析成功授权失败返回权限不足
    3. 如果解析失败返回未认证

3.4 JWT作用

  • JWT作用是什么(数据格式三部分 头,有效载荷,签名)
    参考:
    1. 携带用户的身份信息,一般包括id username.但是不会携带一些敏感信息(password不会携带),例如:
      sub:“{‘userId’:‘1’,‘username’,‘王翠花’}”
    2. 保证携带的信息不会在传输过程中遭到篡改(解析端使用同样的算法对比签名)
  • JWT携带的信息是什么(网络传输的数据,所以他不易过大)
    • userId(必带)
    • username(展示哪个带哪个)
    • nickname(展示哪个带哪个,一般都是nickname)
    • autorities:用户的权限信息(取决于权限系统是否独立)
  • JWT在传输过程中泄露传递信息怎么办
    参考: JWT本身不是加密安全的,基本上是明文的传递,如果需要信息安全,可以对JWT在生成时进行加密,在解析时进行解密操作.(RSA非对称加密.生成jwt一端加密,解析jwt一端去解密,外界破解的可能性微乎其微)
    授权系统

3.5 授权流程

在这里插入图片描述
和没有授权系统对比,加入授权系统的流程仅仅是在单体架构系统拿到JWT之后有变化

  1. 解析JWT 获取用户信息,携带userId访问授权系统
  2. 授权系统根据userId从数据库或者缓存拿到权限信息
    1. 这时候的权限如果是从数据库读的就是实时的,如果是引入缓存需要考虑缓存一致性问题
  3. 授权系统返回权限信息
  4. 单体架构系统授权判断
  5. 根据判断结果返回给用户数据
    1. 授权通过,返回正确数据
    2. 授权失败,返回权限不足信息

3.6 JWT结构

Json Web Token由以下三部分组成:

  • Header(头部)
  • Payload(载荷)
  • Signature(签名)

一个典型的JWT形式如:xxx.yyy.zzz,由两个点.间隔。

3.6.1 Header

典型的JWT header包含两个部分:(1) token类型,即JWT。(2) 所使用的签名算法,比如HMAC SHA256或者RSA。

{
	"alg": "HS256",
	"typ": "JWT"
}

该JSON以Base64Url加密(可以被对称解密)后形成了JWT的第一部分:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

3.6.2 Payload

JWT token的第二部分是包含了声明的payload,声明是一个实体的表述加上额外信息,一共有三种形式的声明:注册、共有和私有。

  • 注册声明(建议但不强制):
    • iss: jwt签发者
    • sub: jwt使用者
    • aud: jwt接收者
    • exp: jwt过期时间,该时间必须大于签发时间
    • nbf: 定义在某个时间之前,该jwt都是不可用的
    • iat: jwt签发时间
    • jti: jwt唯一身份标注,主要用于一次性token,从而避免重放攻击
      (注:为了保持紧凑,注册声明都是三个字母)
  • 公有声明:
    公有声明可以加入任何信息,一般会添加用户相关信息或者业务需要的信息,但不建议添加敏感信息,因为该部分会在客户端解密。
  • 私有声明:
    私有声明是提供者和使用者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密,基本等同于明文信息。
{
    "iss":"#发行人",
    "exp":"#到期时间",
    "sub":"主题(自定义数据)",
    "aud":"用户",
    "nbf":"在此之前不可用",
    "iat":"发布时间"
}

然后对其进行base64加密,得到JWT的第二部分:

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

3.6.3 Signature

JWT的第三部分是签名信息,Signature由三部分组成:

  • header(base64加密后)
  • payload(base64加密后)
  • secret (盐)

Signature需要将base64加密后的header和payload使用.连接,然后通过header所使用的加密方式进行加盐(secret)组合加密,产生了jwt的第三部分。以使用HMAC SHA256算法为例,signature以如下方式产生:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

Signature被用于验证信息在传输过程中没有被更改,或者在token以私钥加密的条件下,也可以验证JWT的发送者是否是其所自称的身份。

注:secret保存在服务端,jwt的签发也发生在服务端,secret是用来进行jwt的签发和验证的。因为,它就是服务端的私钥,任何场景下都不应该被泄露出去。

如图是一个完整的jwt token示例:
在这里插入图片描述

3.7 JWT认证的优势

  • 简洁:JWT Token数据量小,传输速度也很快
  • 因为JWT Token是以JSON加密形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持
  • 不需要在服务端保存会话信息,也就是说不依赖于cookie和session,所以没有了传统session认证的弊端,特别适用于分布式微服务
  • 单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话, token可以被保存在客户端的任意位置的内存中,不一定是cookie,所以不依赖cookie,不会存在这些问题
  • 适合移动端应用:使用Session进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到Cookie(需要 Cookie 保存 SessionId),所以不适合移动端

因为这些优势,目前无论单体应用还是分布式应用,都更加推荐用JWT token的方式进行用户认证
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值