think icon indicating copy to clipboard operation
think copied to clipboard

session、cookie和SSO

Open bytemofan opened this issue 6 years ago • 0 comments

什么是session?

  • cookie的工作原理
  • session的工作原理

如何使用session? 什么是SSO? SSO的原理是什么?

最近在开发nodejs项目,使用到了express-session中间件,且需要对接公司的SSO,对接过程中,对session了解的不够深入,一定程度上影响了效率,遂在此做点总结,加深印象。

什么是session?

session就是一次客户端和服务端的会话。

广义的会话是啥?也就是客户端发一次请求到服务端,服务端响应后给客户端一个回复,就完成了一次会话。

那么问题来了,我们知道,http请求是无状态的,也就是不做任何记录,那我下一次客户端请求服务器,这次请求和上一次隔得时间很短,且是同一个用户的请求,如果这个请求是登录的话,我们是不是就认为它们是两次会话,那是不是得登录两次?

明显不可能是吧,那就需要我们记住请求的状态信息,把一段时间内的某些请求,认为是同一次会话。就像打电话一样,A打给B,接通后,聊了很多东西,直达挂断电话之后,这次会话才算完成。所以狭义的会话就是指:

浏览器和服务端建立连接后,服务端会存储一个状态信息,只要这个存储信息还没有被销毁或者失效,那么会话就会一直持续,状态有效期内,无论发了多少次请求,都被认为是一次会话。

而这个状态信息怎么存储呢?用的就是session。

同样的,cookie也可以用来存储http状态,不过一般cookie是用于客户端存储用户信息的,session则是用于服务端存储用户信息的。一般来说,session是一个抽象概念,cookie才是实际存在的东西,session的实现需要借助cookie来实现(cookie禁用时,session可能会没法用,但也有其它办法实现,比如借助URL等)。

要了解session的实现,我们先来了解一下cookie的工作原理。

cookie的工作原理

image

如图所示,cookie是在服务端创建的,但保存在浏览器端。在cookie有效期内,后续的浏览器的请求就会带上对应的cookie,服务端识别cookie后就可以知道当前发起请求的用户是哪一个,而且,浏览器下次再次需要相同信息时,比如用户名什么的,可以直接从cookie里取得,而不用再次发起请求获取。

cookie有如下特点:

  • 每一个cookie文件大小超过4kb浏览器不识别
  • 浏览器保存cookie的数量有限,至多300个
  • cookie不安全,可能会泄露用户信息
  • 浏览器可以禁用cookie
  • 默认情况下,浏览器关闭时就会销毁cookie(临时cookie)
  • cookie遵守同源策略

cookie一定程度上解决了http请求无状态的问题。但由于cookie不安全和服务端不可控,一般很少用cookie来作为用户的登录标识信息。

session的工作原理

image

session的实现是借助了cookie的机制,只是session在浏览器端保存的只有sessionid,其它的信息则是保存在了服务端,sessionid是一个不会重复的,难以伪造的字符串。

如何使用session?

session的实现其实也不难,它就是一个特殊的cookie而已,一般每个后端框架都会提供一个session处理模块,比如express的express-session,koa的koa-session等,这里我们以最常用的express-session举例:

安装express-session:

$ npm install express-session --save

一般我们需要把session持久化,防止访问状态的丢失。持久化可以使用redis,这里依赖connect-redis模块:

$ npm install connect-redis --save

在app.js里:

const Session = require('express-session')
const RedisSession = require('connect-redis')(Session)
...
app.use(session({
  store: new RedisSession({
    host: '10.x.x.111',
    port: 3700,
    no_ready_check: true
  }),
  cookie: {
    path: '/',
    httpOnly: true,
    secure: false,
    maxAge: null
  },
  resave: true,
  saveUninitialized: true,
  secret: 'service of test'
}))

从session里取数据:

function getSession(req, res, next) {
    let { sessionid } = req.cookies
    if(sessionid) {
       let { user } = req.ression
       return res.json({
        code: 1
        user: user
      })
    }
}

设置数据到session:

function getSession(req, res, next) {
    let { user } = req.ression
    if(user) {
       user.name = '开发'
       user.id = '2322',
       user.role=10
    }
}

什么是SSO?

SSO(single-sign-on),在多个系统中,用户只需在其中一个系统上登录,其它受信任的系统则不用用户再重复登录,它是将这次主要的登录映射到其他应用中用于同一个用户的登录。一般用于企业内部系统管理解决方案。

SSO的原理是什么?

相同domain下的SSO

如果你的系统全部都拥有相同的domain,那么我们直接再服务端维护一个带有过期时间的sessionid就好了。用户在其中一个系统上登录了会生成一个sessionid,且把它写到相同的domain下去,然后在再去访问其它系统时,由于处于相同的domain下,所以可以拿到sessionid去请求用户数据。

不同domain下的系统的SSO

不同domian下的系统,则不能共享sessionid了,一般的做法是,借助一个中间sever,专门的做系统的认证,这一套流程已经有开源的实现:CAS。现在的好多SSO认证服务器,也或多或少的是基于这一套来做的,只是可能出于安全性等的考虑,使用者可能会在理解这套系统的基础上,加入一些自己的认证流程。

CAS的一般流程如下: image

bytemofan avatar Sep 07 '18 13:09 bytemofan