01.redis单点登录
# 01.redis实现单点登录
使用Redis实现分布式部署单点登录(单点登录第一种方法:redis分布式存储解决方案)
因为这个项目是一个分布式部署的项目,而且我们采用的是nginx负载均衡的策略,导致了每一个服务器都需要开辟一个空间来进行用户信息的维护,消耗了大量的资源,所以,我当时使用到了Redis来作为维护用户信息的空间,将用户登录的信息存入Redis中,并且在存入时设置key的过期时间,所有的服务器共用一个Redis,每次进行操作时只需要去Redis中去判断这个用户是否存在,存在的话就说明这个用户现在是登录状态,不存在就说明这个用户没有登录,或者登录已经失效,让用户进行重新登录。
- 为什么会存在单点登录的问题
- session默认是存储在当前服务器的内存中,如果是集群,那么只有登录那台机器的内存中才有这个session
- 比如说我在A机器登录,B机器是没有这个session存在的,所以需要重新验证
- 如何解决这个单点登录问题
- 不管在那一台web服务器登录,都会把token值存放到我们的一个集中管理的redis服务器中
- 但客户端携带token验证的时候,会先从redis中获取,就实现单点登录
- 现实举例
- 比如你写的一个tornado项目,分别部署到A,B两台机器上
- 如果直接使用session,那么如果在A机器登录,token只会在A服务器的内存
- 因为请求会封不到A,b连个机器,如果这个请求到了B机器,B的内存中没有就会让重新登录
- 所以登录A机器的时候我们应该把token值写入到redis中,A/B机器登录,都从redis中获取token进行校验
# 02.多站点单点登录实现方案
# 2.1 需求说明
有这么个场景,公司下有多个不同域名的站点
我们期望用户在任意一个站点下登录后,在打开另外几个站点时,也是已经登录的状态,这么一过程就是单点登录。
因为多个站点都是用的同一套用户体系,所以单点登录可以免去用户重复登录,让用户在站点切换的时候更加流畅,甚至是无感知。
单点登录所要实现的就是,某一站点登录后,将其登录态会同步到其他另外几个站点。
我们分两部分,先说单个站点的登录流程,在说同步登录态的流程。
# 2.2 登录流程
- 用户首次打开站点,服务端生成 session 对象,此时 session 中没有用户信息,同时服务端往浏览器写入 cookie
- 用户触发登录操作服务端校验参数处理登录逻辑后,生成用户信息,将用户信息写入 session 对象,更新缓存 redis
# 2.3 同步登录态
- 为便于描述,我们假设有两个站点,分别为A站点和B站点。
- 因为A、B站点的域名不同,基于同源策略, cookie 是没法共享的
- 所以我们采取主动请求的方式,将用户唯一凭证通过接口传过去。
- 大致流程如下
- A站点完成登录逻辑后,将用户凭证返回到浏览器,为了安全性,在传输凭证前,对凭证进行加密,可采用 AES 或者 RSA
- A站点的客户端获取到凭证后,调用B站点提供的同步登录态接口,将凭证传过去
- B站点的服务端获取到凭证,解密,查询缓存中的用户信息,创建 session 对象,写入B站点域名下的 cookie 信息
- B站点的登录态同步完成。
# 2.4 同步登录态的场景
上面描述的是当用户首次登录时的同步流程,还需要考虑其他场景
比如,B站点获得的登录态失效了,这时候访问B站点页面,就需要在一次前往A站点同步登录态。
B站点上的页面分为两种,一种是需要登录态才可以访问的,一种是不需要登录态就可以访问的。
第一种情况下,需要重定向到A站点,可为啥要绕回去A站点呢?
- 因为此时我们也不知道A站点的登录态是否也失效了,所以需要回到A站点判断A站点当前的登录态
- 若A站点登录态也失效了,那么就去登陆页进行重新登录
- 若A站点是有登陆态的,那么只要在做一次同步登录态的操作即可。
第二种情况
- 虽然B页面不需要登录态就可以查看,但是企业网站往往会在页面的head部分标记用户的登录态
- 所以为了让这部分的显示正常,我们在当前页面异步的去更新登录态即可。
# 2.5 跨域请求
因为要在A站点请求B域名下的接口,所以会有跨域问题,跨域问题常用的解决方式有如下几种
JSONP 很常见很通用的一种方式
Image 利用 Image src 可以绕过同源策略,所以通过构建一个 Image 发送给请求也是可行的,同时服务端也不需要做太多修改。
CORS 老的浏览器就没法支持,需要在服务端设置 Access-Control-Allow-Origin,允许任何域或指定的域发起的请求都可以获取当前服务器的数据。