think
think copied to clipboard
session、cookie和SSO
什么是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的工作原理
如图所示,cookie是在服务端创建的,但保存在浏览器端。在cookie有效期内,后续的浏览器的请求就会带上对应的cookie,服务端识别cookie后就可以知道当前发起请求的用户是哪一个,而且,浏览器下次再次需要相同信息时,比如用户名什么的,可以直接从cookie里取得,而不用再次发起请求获取。
cookie有如下特点:
- 每一个cookie文件大小超过4kb浏览器不识别
- 浏览器保存cookie的数量有限,至多300个
- cookie不安全,可能会泄露用户信息
- 浏览器可以禁用cookie
- 默认情况下,浏览器关闭时就会销毁cookie(临时cookie)
- cookie遵守同源策略
cookie一定程度上解决了http请求无状态的问题。但由于cookie不安全和服务端不可控,一般很少用cookie来作为用户的登录标识信息。
session的工作原理
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的一般流程如下: