【SSO单点登录】传统Cookie和Session会话机制

3,136 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 1 天,点击查看活动详情

大家好,我是melo,一名大三后台练习生,不知不觉练习时间长达一年了!!!

💎专栏引言

SSO,Single Sign On,通过用户的一次性鉴别登录。当用户在[身份认证服务器]上登录一次以后,即可获得访问单点登录系统中其他关联子系统的权限,有没有觉得这个似乎很熟悉呢,作为我们大学狗们,各种教务系统,学校统一认证是不是都是类似的【一次登录,处处通行】

为什么学校这么喜欢搞SSO?

  1. 因为方便阿,老师不用记那么多密码hhh
  2. 管理员管理起来也很方便,只需要维护一个账号,一个认证中心,当有新的子系统,只需要授权即可

👉本篇速览

早在JavaWeb篇,我们就听说了Cookie这么个东西,平时浏览器也经常会出现,是否信任Cookie等弹窗,听起来是个很高级的东西。这篇将从如下几点,来带你逐一攻破ta:

  • 传统会话流程

    • 登录状态会保持多久
  • Cookie存在的问题

    • 浏览器禁用了Cookie,session还能用吗

    • 无法防止CSRF攻击

      • CSRF攻击的流程
    • 不可跨域

      • domain二级域名共享
  • Session存在的问题

传统会话流程

  1. 浏览器在第一次访问后台服务器的时候,后台服务器会在服务端创建session对象,并存储到map中.key是session的id【JSESSIONID】,value是session对象本身.
  2. 在响应的时候会把session的id通过cookie的方式写到客户端浏览器中.
  3. 浏览器会在本地的目录中把JSESSIONID写入到本地的cookie中.
  4. 在后续的请求中,都会读取本地的cookie中的内容,并在请求的时候带上对应的cookie
  5. 通过cookie中的JSESSIONID,能到后台服务器中的map,根据key,找到对应的session对象,也就相当于能找到自己的登录状态和身份信息,这样就实现了保持登录状态的作用对应的session对象,也就相当于能找到自己的登录状态和身份信息,这样就实现了保持登录状态的作用

登录状态会保持多久

如果理解了上边,其实可以发现session中的对象就存储了我们用户的登录信息,所以登录状态就取决于session的过期时间。
默认情况下,session是30min失效,这个可以通过配置设置,当然,我们也可以主动销毁session

session.invalidate();

Cookie存在的问题

浏览器禁用了Cookie,session还能用吗

客户端禁用了cookie的话,也就没有JSESSIONID,没法到后台服务器中找到对应的session对象,也就没法维护登录状态,此时还有没有别的方式来传递这个JSESSIONID呢?

  • 可以将 SessionID 放在请求的 url 里面, melo.con/?JSESSIONID…  。这种方案的话可行,但是安全性和用户体验感降低。所以,我们可以对 JSESSIONID 加密之后再传给后端。

不可跨域

假设我们现在有一个A网页: melo.com和 B 网页: melo.com/login ,以及C 网页 carmelo.com
从A网页跳转到B网页的时候,浏览器会自动携带cookie过去【因为同域】

而如果是从B网页跳转到C网页的话,由于不同域,此时是不会携带cookie过去的,也就无法实现cookie共享

domain二级域名共享

正常情况下,同一个一级域名下的两个二级域名如 www.melo.comimages.melo.com 也不能交互使用Cookie,因为二者的域名并不严格相同。如果想所有 melo.com 名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数,例如:

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie

cookie.setDomain("melo.com"); // 设置域名

无法防止CSRF攻击

CSRF攻击的流程

比如现在我们有这样一个后台接口:www.smallMing.com/transfer?to… ,点击【转账按钮就会调用】,作用是转账给xxx,后台做了安全校验,登录后会存储一份session在服务端,当发起该请求时,会根据前端的cookie,校验是否跟session中的一致,来确保是本人操作

看起来无懈可击,至少目前是这样

现在:

  1. 小明在A网站,登录了,存储了cookie,后台也存储了session,建立起登录会话,此时点击按钮转账,成功按照自己的输入,转账给了想要转的人,一切正常
  2. melo准备搞一下小明,于是在A网站,挂了一个隐秘的链接,此链接会去访问melo写好的B网站,在B网站里边,有这样一段代码
<img src=http://www.smallMing.com/transfer?toUserId=11&money=1000>

注释:浏览器会依据加载的域名附带上对应域名cookie
script、image、iframe的src都不受同源策略的影响。所以我们可以借助这一特点,实现跨域,在B网站可以去调用A网站的接口

  • 所以进入B网站后,就会调用A网站的该接口,由于先前的cookie已经确保了身份,所以此时浏览器调用的时候,进入后台,后台按上述流程重新判断后,认为的确是小明本人发出的操作,所有该请求认为是合法的,会执行成功,小明也就乖乖转账了100元给了melo,这波是melo大获胜!

Session存在的问题

  1. 服务端需要存储session,占用内存高
  2. 不同服务器,无法共享session【分布式的场景】,这种情况下通常需要借助redis等数据库来做存储

没有什么是加一层解决不了的hhh

💠下篇预告

  • 本篇作为SSO的开门篇,先简单聊聊传统的Cookie会话机制,接下来再一步一步过渡到分布式session【spring session的原理】,以及token机制。
    • 之后才正式进入我们的主菜,大家敬请期待~

🧿友链