是这样的,之前有说过,项目的新模块都是用单页面应用来弄的,一个flow,或者说一个模块就是一个单页面应用。
这里就有一个问题,就是多个应用之间我如何共享session,我总不能退出来后重新登录吧,这里就来了解下,单页面应用之间是如何共享session的。好吧,标题也写了,就是SSO(单点登录)。具体项目上长啥样,这里记录一下- -,顺便写点之前的疑惑和其解答。只想看单点登录的解决方案,可以直接看这个篇文章单点登录(SSO)解决方案介绍
前后端如何保存session
在了解SSO之前,先了解session的本质是什么。说实话,在最开始学习web的时候有过这样的疑问,http明明是无状态的,请求结束后就断开连接了,为啥还能有session的存在啊。
其实session原理是这样的,在浏览器请求的时候浏览器会附带有cookie,而服务器中会判断cookie是否有特定的token,如果不存在,则此次请求是一个新的会话,如果存在,判断其token是否存在记录,不存在或者记录此token已经过期,则也是一个新的session。
如果是一个新的session,生成token,放入response的cookie中,前端会保存cookie。而cookie的生命是可设置的,如果不设置的话默认为浏览器关闭后清除cookie。所以最开始学习java web的时候书上或者视频里说一个session就是打开网站到关闭网站的那些,都是傻逼,吊玩意儿不懂。
了解session的原理后,我们就知道了,前端是使用cookie保存session标识位,后端的话,可以自建容器或者使用redis之类的保存cookie。
SSO具体实现
在之前的项目中新模块使用spa开发,即进入新模块就是跳转到一个不同页面。这个时候项目中的express写的node层面的代码获得request附带的cookie,去请求登录系统的接口,判断此token,返回对应状态码,让前端判断。做一些类似过期回到登录页面的操作。
但是这里有个问题,就是跨域的时候cookie不共享,要怎么设置cookie,这里有两个方案
网页同属一个二级域
cookie可以设置在自己的域和顶域,比如a.app.com可以设置app.com的cookie,而b.app.com可以访问app.com的cookie。(但是不能设置为公共域名cookie,比如.com .cn)网页域名完全不同
当网页域名完全不同时,就需要一个单独的登录系统具体行为如下:
当app a需要登录的时候,定向到SSO进行登陆后,定向回到a并附加系统生成token,a使用token访问SSO系统,判断token可用,然后设置a系统域名下token。
当app b需要登陆,但是用户状态已经登录时,b访问SSO,SSO直接重定向回到b并返回token,b去在向SSO验证token后,在b系统cookie中写入token。
这里注意拿到token之后一定要去校验,防止伪造token。
cookie相关
由于身份认证和cookie关系密切,所以这里主要记录一些cookie相关内容
- 常见属性
maxAge。用于设置cookie存在时间,单位为秒,为负数的时候就是关闭浏览器后删除,默认-1。用expires也可以设置,但是expires属性是http1.0的协议内容,maxAge是http1.1内容,maxAge的优先级高于expires。
secure这个属性表示此cookie只在https的请求中附带。
httpOnly这个禁止用户在js中操作此cookie,主要是防止xss,即防止插入页面的脚本直接获得cookie中的token然后任意访问服务器。
domain、path这两个主要是设置cookie的具体地址,如果这两个值都设置了,那么该cookie只会在该路径被发送到服务端。当然啦,再怎么设置cookie也没法跨域。 - 小tips
浏览器的fetch默认不附带cookie,需要自己设置fetch属性credential为true。
跨域请求也是不附带cookie,需要后端设置Access-Control-Allow-Credentials,并且Access-Control-Allow-Origin也必须指定origin,而不能使用*进行通配。