单点登录与注销系统原理与实现

一、单系统登录机制

1、http无状态协议
  web应用采用browser/server架构,http作为通信协议http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关联,这个过程用下图说明,三次请求/响应对之间没有任何联系(解释: 主要就是因为http是无状态的协议)
  在这里插入图片描述
  但这也同时意味着,任何用户都能通过浏览器访问服务器资源,如果想保护服务器的某些资源,必须限制浏览器请求;要限制浏览器请求,必须鉴别浏览器请求,响应合法请求,忽略非法请求;要鉴别浏览器请求,必须清楚浏览器请求状态。既然http协议无状态,那就让服务器和浏览器共同维护一个状态吧!这就是会话机制
  
2、会话机制
  浏览器第一次请求服务器,服务器创建一个会话,并将会话的id作为响应的一部分发送给浏览器,浏览器存储会话id,并在后续第二次和第三次请求中带上会话id,服务器取得请求中的会话id就知道是不是同一个用户了,这个过程用下图说明,后续请求与第一次请求产生了关联
  (解释: 登录的用户在session里面是可以查询到的已经存储的isLogin属性设置为true)
  在这里插入图片描述
  服务器在内存中保存会话对象,浏览器怎么保存会话id呢?你可能会想到两种方式:
①请求参数
②通过cookie实现

  将会话id作为每一个请求的参数,服务器接收请求自然能解析参数获得会话id,并借此判断是否来自同一会话,很明显,这种方式不靠谱。
  那就浏览器自己来维护这个会话id吧,每次发送http请求时浏览器自动发送会话id,cookie机制正好用来做这件事。cookie是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,浏览器发送http请求时自动附带cookie信息

tomcat会话机制当然也实现了cookie(解释: 就是当客户端访问tomcat的时候,tomcat也可以给客户端发送一个cookie),访问tomcat服务器时,浏览器中可以看到一个名为“JSESSIONID”的cookie,这就是tomcat会话机制维护的会话id,使用了cookie的请求响应过程如下图
  在这里插入图片描述
  3、登录状态
  有了会话机制,登录状态就好明白了,我们假设浏览器第一次请求服务器需要输入用户名与密码验证身份,服务器拿到用户名密码去数据库比对,正确的话说明当前持有这个会话的用户是合法用户,应该将这个会话标记为“已授权”或者“已登录”等等之类的状态,既然是会话的状态,自然要保存在会话对象中,tomcat在会话对象中设置登录状态如下
  在这里插入图片描述
  实现了登录状态的浏览器请求服务器模型如下图描述
  在这里插入图片描述
   每次请求受保护资源时都会检查会话对象中的登录状态,只有 isLogin=true 的会话才能访问,登录机制因此而实现。

二、多系统的复杂性

web系统早已从久远的单系统发展成为如今由多系统组成的应用群,面对如此众多的系统,用户难道要一个一个登录、然后一个一个注销吗?就像下图描述的这样
在这里插入图片描述
web系统由单系统发展成多系统组成的应用群,复杂性应该由系统内部承担,而不是用户。无论web系统内部多么复杂,对用户而言,都是一个统一的整体,也就是说,用户访问web系统的整个应用群与访问单个系统一样,登录/注销只要一次就够了
在这里插入图片描述
虽然单系统的登录解决方案很完美,但对于多系统应用群已经不再适用了,为什么呢?

单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器与服务器之间维护会话状态。但cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名)(解释: 就是说一个服务器产生的cookie只能在该服务器下使用,不能在其他服务器使用,而我们的分布式多系统就不一样了,有可能这个请求打到这台服务器上,下一个请求就打到另一台服务器上了,所以某一个服务器产生的cookie不能在所有其他服务器上起作用),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie,意思就是说该服务器产生的cookie,那么cookie的key就是这个服务器的域名(解释:也就是说客户端可以有很多个cookie,然后在负载均衡的情况下访问不同的服务器的时候,虽然每次访问都带了很多的cookie访问某一台服务器,但是浏览器可以拦截其他的cookie,只用本服务器产生的cookie)
  在这里插入图片描述
  既然这样,为什么不将web应用群中所有子系统(一个web应用的功能可能被分割成多个模块)的域名(解释: 每个模块可能有不同的域名,但是所有模块的功能总和组成了一整个web应用)统一在一个顶级域名下,例如“*.baidu.com”,然后将它们的cookie域设置为“baidu.com”,这种做法理论上是可以的,甚至早期很多多系统登录就采用这种同域名共享cookie的方式。(解释: 一个服务器产生的cookie只能在该服务器下使用,为了让浏览器访问各个子模块的时候都能够把共同的cookie带过去,那只有一种情况,那就是cookie的名字或者域名都是一个顶级域名,能够进行各个子模块的通配,从而各个子模块都可以接收这个cookie)
  下图是我对这段话的理解:
  在这里插入图片描述

然而,可行并不代表好,共享cookie的方式存在众多局限。首先,应用群域名得统一;其次,应用群各系统使用的技术(至少是web服务器)要相同,不然cookie的key值(tomcat为JSESSIONID)不同(小疑问:就算web服务器相同,就一定能保证cookie的key值相同吗?还有不是说各个子模块的顶级域名已经相同了吗,为什么还有保证key值一样 啊?可能是说域名相同,只是能够确保能够让所有服务器都能够接收到这个cookie,但是接收到以后还要根据key值来取value值,所以key值最好是一样的,这样更方便些,而如果web服务器相同的话,那么key的值就相同(例如:tomcat为JSESSIONID)),无法维持会话,共享cookie的方式是无法实现跨语言技术平台登录的,比如java、php、.net系统之间;第三,cookie本身不安全。

因此,我们需要一种全新的登录方式来实现多系统应用群的登录,这就是单点登录

三、单点登录

什么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分
  1、登录
  相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌(tokens)实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理,用下图说明
解释: 浏览器首先访问系统1,系统1检测到用户没有登录。于是带上系统1的地址转发到sso认证中心,也发现没有登录,于是带上系统1的地址来到登录页面进行登录,登录完毕之后,sso认证中心就开始创建全局会话(
小疑问:是如何创建全局会话的?
答:sso认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话),创建授权令牌tokens,接着有了tokens令牌之后就可以跳转到系统1的地址了,这个时候系统1向sso认证中心校验令牌有效,sso认证中心把系统1的地址注册到sso认证中心上,然后返回给系统1,令牌有效,于是浏览器就可以访问系统1了。
再接着如果浏览器要访问系统2的话,在系统2上一验证,发现没有登录,这个时候就带着系统2的地址跳去sso认证中心,sso认证中心上验证已经登录,于是把令牌tokens发送给系统2,这个时候系统2再次带着系统2的地址和令牌来到sso认证中心验证时,令牌肯定是有效的,然后sso中心把系统2的地址注册到本地上,接着告诉系统2,令牌有效,于是浏览器就可以和系统2进行局部会话了

在这里插入图片描述
  下面给出最详细的权威的解释:在这里插入图片描述
  2、注销
  单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明
  在这里插入图片描述
  在这里插入图片描述

四、部署图

单点登录涉及sso认证中心与众多子系统,子系统与sso认证中心需要通信以交换令牌、校验令牌及发起注销请求,因而子系统必须集成sso的客户端,sso认证中心则是sso服务端,整个单点登录过程实质是sso客户端与服务端通信的过程,用下图描述
  小疑问: 如果不加网络防火墙会怎么样? 防火墙怎么配置呢?有配置文件吗?还是只需要dos命令就行
在这里插入图片描述
sso认证中心与sso客户端通信方式有多种,这里以简单好用的httpClient为例,web service、rpc、restful api都可以

五、实现

只是简要介绍下基于java的实现过程,不提供完整源码,明白了原理,我相信你们可以自己实现。sso采用客户端/服务端架构,我们先看sso-client与sso-server要实现的功能(下面:sso认证中心=sso-server)
  在这里插入图片描述
  1、sso-client拦截未登录请求
  java拦截请求的方式有servlet、filter、listener三种方式,我们采用filter。在sso-client中新建LoginFilter.java类并实现Filter接口,在doFilter()方法中加入对未登录用户的拦截
  在这里插入图片描述
  2、sso-server拦截未登录请求
  拦截从sso-client跳转至sso认证中心的未登录请求,跳转至登录页面,这个过程与sso-client完全一样
  3、sso-server验证用户登录信息
  用户在登录页面输入用户名密码,请求登录,sso认证中心校验用户信息,校验成功,将会话状态标记为“已登录”
在这里插入图片描述
4、sso-server创建授权令牌
  授权令牌是一串随机字符,以什么样的方式生成都没有关系,只要不重复、不易伪造即可,下面是一个例子
  在这里插入图片描述
  5、sso-client取得令牌并校验
  sso认证中心登录后,跳转回子系统并附上令牌,子系统(sso-client)取得令牌,然后去sso认证中心校验,在LoginFilter.java的doFilter()中添加几行
在这里插入图片描述
小疑问: httpclient的参数是这样吗?不解,httpPost括号里面的参数

6、sso-server接收并处理校验令牌请求
  用户在sso认证中心登录成功后,sso-server创建授权令牌并存储该令牌,所以,sso-server对令牌的校验就是去查找这个令牌是否存在以及是否过期,令牌校验成功后,sso-server将发送校验请求的系统注册到sso认证中心(就是存储起来的意思)

令牌与注册系统地址通常存储在key-value数据库(如redis)中,redis可以为key设置有效时间也就是令牌的有效期。redis运行在内存中,速度非常快,正好sso-server不需要持久化任何数据。

令牌与注册系统地址可以用下图描述的结构存储在redis中,可能你会问,为什么要存储这些系统的地址?如果不存储,注销的时候就麻烦了,用户向sso认证中心提交注销请求,sso认证中心注销全局会话,但不知道哪些系统用此全局会话建立了自己的局部会话,也不知道要向哪些子系统发送注销请求注销局部会话
  小疑问: 下面这幅图看不明白???在这里插入图片描述
  7、sso-client校验令牌成功创建局部会话
  令牌校验成功后,sso-client将当前局部会话标记为“已登录”,修改LoginFilter.java,添加几行(解释: 因为浏览器可能会访问多个子模块,从而产生多个局部会话,相当于浏览器与每个子模块服务器之间都有一个session)
  在这里插入图片描述
  sso-client还需将当前会话id(sessionID)与令牌绑定(解释: 因为一旦注销,那么就可以根据sessionID来取出令牌,最后到sso认证中心上检测存在该令牌,然后销毁全局会话,从而销毁所有的令牌),表示这个会话的登录状态与令牌相关,此关系可以用java的hashmap保存,保存的数据用来处理sso认证中心发来的注销请求(解释:就是说一个点发起了注销请求之后,sso认证中心接收到了之后,从而销毁全局会话,然后取出所有web应用各个模块系统的注册令牌并销毁,然后通知各个模块,令牌失效,各局部session全部销毁,这样一来,用户就不能和各子模块再次交互通信了
  重点: 本质上只有一个全局session会话(就是浏览器与sso认证中心的会话),其他的都是局部session,一旦消除全局session,那么局部session也会被通知由于各自的令牌销毁从而导致本局部session也要销毁
  
  8、注销过程
  用户向子系统发送带有“logout”参数的请求(注销请求),sso-client拦截器拦截该请求,向sso认证中心发起注销请求
  在这里插入图片描述
   sso认证中心也用同样的方式识别出sso-client的请求是注销请求(带有“logout”参数),sso认证中心注销全局会话
   在这里插入图片描述
   解释: 全局session(浏览器跟sso认证中心之间的session)注销之后触发LogoutListener,在LogoutListener中还要销毁所有的各个web系统的子模块的令牌

sso认证中心有一个全局会话的监听器,一旦全局会话注销,将通知所有注册系统注销
  在这里插入图片描述
 

第二篇登录理解

1、首先我们会有三台机器,一个统一认证中心(sso),两个系统(crmwms
在这里插入图片描述
 
2、这个时候我们向crm系统发起一个请求,第一次访问www.crm.com/employee,发现本地并没有cookie,然后在crm系统中查看下是否有局部会话,发现也没有,这个时候就需要去统一认证中心查看是否登录,并且要把当前请求的地址作为参数传递给统一认证中心
在这里插入图片描述
 
3、这个时候调用sso.com中的checkLogin方法查看是否有全局会话(如果有则说明已经登录),但是在本地浏览器sso.comcookie中并没有发现cookie,所有也没有全局会话,此时需要把url从地址栏中获取出来,并把这个参数放入到request域中,转发到统一认证中心的登录页面,进行登录
在这里插入图片描述
 
4、转发到统一认证中心登录页面后,需要把url放入到登录表单中,因为登录成功之后,需要继续访问上次访问的网址:www.crm.com/employee
在这里插入图片描述
 
5、在统一认证中心登录页面输入账号和密码,后台登录成功以后,需要创建一个session对象,并且还要创建令牌tokensession.settribute("token","OSPIKeVNE5fyjV8w");,并把这个token信息存储到session对象中以及后台的数据库中,方便后续的校验,然后请求响应给浏览器,并把sessionIdcookie的形式写入到本地浏览器中,然后重定向到www.crm.com/employee?token=OSPIKeVNE5fyjV8w,此时请求中带着一个token令牌
在这里插入图片描述
 
6、浏览器重定向到www.crm.com/employee?token=OSPIKeVNE5fyjV8w过滤器拦截到请求,判断是否有局部会话,发现没有,但是却有token参数,由于怕人为伪造token参数,此时需要判断token的有效性,需要去统一认证中心判断该token是否来自于统一认证中心
在这里插入图片描述
 
7、使用HttpURLConnection发送请求,www.sso.com/employee?token=OSPIKeVNE5fyjV8wsso.com系统获取到token,然后查询数据库,查询数据中是否存在该token,如果存在返回true,否则返回false
在这里插入图片描述
 
8、如果统一认证中心返回true,就创建局部会话,并设置属性isLogin=true,放行请求,然后返回响应,将sessionId存储到cookie
在这里插入图片描述
 
9、然后第二次访问的时候,请求会把本地的cookie带上(sessionId),如果在服务器中能找到与之对应的session,获取isLogin属性,如果值为true,则说明有会话,此时就放行请求
在这里插入图片描述
 
10、然后当我们访问wms系统,第一次访问,本地没有对应的cookie,服务器也没有局部会话,然后去统一认证中心查看是否登录,并且要把当前请求的地址作为参数传递给统一认证中心
在这里插入图片描述
 
11、此时在sso.com服务器中根据JSESSIONID可以获取到对应的session对象,说明统一认证中心已经登录了,然后重定向到wms.com,并把token带上
在这里插入图片描述
 
12、浏览器重定向到www.wms.com/employee?token=OSPIKeVNE5fyjV8w过滤器拦截到请求,判断是否有局部会话,发现没有,但是却有token参数,由于怕人为伪造token参数,此时需要判断token的有效性,需要去统一认证中心判断该token是否来自于统一认证中心
在这里插入图片描述
 
13、sso.com获取到tonken,并查询数据库是否存在该token,存在返回true,否则返回false;如果统一认证中心返回true,就创建局部会话,并设置属性isLogin=true,放行请求,然后返回响应,将sessionId存储到cookie
在这里插入图片描述
 
14、第二次访问,请求就会把本地的cookie带上(sessionId),然后在服务器找到与之对应的session,获取isLogin属性,若值为true,则说明有局部会话,此时放行请求
在这里插入图片描述

单点注销流程分析

一、前言

单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明:

format,png

单点注销流程

步骤分析:

1.用户在CRM系统中点击注销按钮.会重定向到统一认证中心的注销方法

2.统一认证中心接受到注销请求之后,会销毁全局的会话.

3.统一认证中心会拿到之前在该系统中注册的子系统集合.

4.依次的调用子系统的登出方法,销毁局部会话.

5.每个系统中的会话都已经销毁之后,跳转到登陆页面.

二、系统中的Cookie和Session存储图解

以下图解是基于单点登录图解,在之前的基础上,添加一些信息来帮我们更好的完成单点注销的功能.

图01:我们在统一认证中心登录成功后.除了需要做这几件事情.

1.创建令牌,后续操作中得发给子系统,相当于间接授权.

2.创建全局会话,并把令牌存储到全局会话中.

3.把令牌信息存储到数据库中的t_token表中.主要是后续客户端校验token的有效性需要查询这种表.

4.重定向到之前用户请求的地址redirectUrl.并把令牌发给该子系统.http://www.crm.com/employee?token=VcnVMguCDWJX5zHa

还需要创建一张t_client_info信息

这张表存储的是究竟有哪些子系统在统一认证中心注册了.

在单点登录的时候拿到注册子系统的集合,依次调用子系统的登出方法.

format,png

单点注销01

图02:我们在CRM系统给统一认证中心发送一个校验令牌token有效性的请求的时候.

除了带上令牌token信息之外.还需要带上如下信息:

1.客户端的登出地址:http://www.crm.com/logout

2.客户端的JSESSIONID(目的是在调用客户端销毁方法的时候能找到对应的会话并销毁)

所以此时请求的地址为:

http://www.sso.com/verify?token=VcnVMguCDWJX5zHa&clientUrl=http://www.crm.com/logout&JSESSIONID=F4C441B40D00A03DD8DDEBF751F2BF01

format,png

单点注销02

图03:当两个系统都已经在统一认证中心注册好之后,数据库表t_token中存储的信息如下图所示.

format,png

单点注销03

图04:我们在CRM系统中点击注销按钮,这个注销按钮的地址其实指向

http://www.sso.com/logout,访问的是统一认证中心的注销方法.

format,png

单点注销04

图05:浏览器发出请求http://www.sso.com/logout,浏览器会根据请求的域名找到本地的sso.com目录cookie,并把cookie里面的信息一并带到服务器.d

通过cookie中的JSESSION可以找到统一认证中心的会话对象.

format,png

单点注销05

图06:拿到统一认证中心的会话对象之后

1.取出会话中的令牌信息token,通过令牌信息在表t_clinet_info中找到之前注册的子系统集合.

2.遍历子系统集合,依次调用子系统的登出方法,并把JSESSIONID带上.

format,png

单点注销06

图07:子系统接受到请求之后,根据JSESSIONID找到对应的会话对象进行销毁.

format,png

单点注销07

图08:需要把令牌信息从数据库中删除.

format,png

单点注销08

图09:清除全局会话对象.

format,png

单点注销09

图10:响应统一认证中心的登陆页面

format,png

单点注销10

统一认证中心与客户端通信方式有多种,这里以简单好用的HttpURLConnection为例,WebService、rpc、restful api都可以.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: (SSO)的优势有哪些? CAS方式实现SSO的优势包括:1)可以有效地减少用户的登录次数;2)可以提供安全的认证服务,保护用户的账号安全;3)可以支持多个应用系统,减少用户登录的麻烦;4)可以跨域访问,支持用户跨域登录。 ### 回答2: CAS(Central Authentication Serivce)是一种单点登录(Single Sign-On,简称SSO)的解决方案。它通过在一个系统中进行身份验证,然后将凭证(ticket)分发给其他系统,以便在这些系统实现单点登录。 在CAS方式中,有三个主要角色:CAS Server、CAS Client和用户。CAS Server是用于身份验证和票证的分发中心,CAS Client是需要访问的应用程序,用户是需要登录并访问这些应用程序的人。 实现CAS单点登录的过程如下: 1. 用户访问一个CAS Client应用程序,并尚未登录。 2. CAS Client检测到用户未登录,将用户重定向到CAS Server的登录页面。 3. 用户在CAS Server登录页面上输入用户名和密码进行身份验证。 4. CAS Server验证用户的凭证,如果身份验证成功,CAS Server会生成一个票证(ticket)并将其存储。 5. CAS Server将用户重定向回原始CAS Client应用程序,并附带这个生成的票证。 6. CAS Client应用程序接收到票证后,它会将该票证发送给CAS Server进行验证。 7. CAS Server验证票证的有效性,如果有效,CAS Server会生成一个ST(Service Ticket),并将其发送给CAS Client应用程序。 8. CAS Client应用程序再次发送ST给CAS Server,CAS Server验证ST的有效性。 9. 如果验证成功,CAS Server会告诉CAS Client应用程序用户已经成功登录,并且CAS Client应用程序可以在当前会话中使用用户的身份。 通过CAS方式实现单点登录有以下优点: 1. 提高用户体验:用户只需登录一次,就可以访问所有CAS Client应用程序,不需要多次身份验证。 2. 简化用户管理:CAS Server负责用户身份验证和管理,避免了在每个应用程序中独立管理用户。 3. 提高安全性:通过票证(ticket)的方式,CAS Server负责身份验证和票证的生成,可以减少密码泄露的风险。 总之,CAS方式实现单点登录,为用户带来了便利和安全性,并简化了应用程序的用户管理。 ### 回答3: CAS(Central Authentication Service)是一种实现单点登录(SSO)的方式。它采用了基于票据的认证机制,使用户只需要登录一次,就能够访问多个相互信任的应用系统。 CAS的工作原理如下: 1. 用户访问需要进行登录认证的应用系统,应用系统检测到用户未登录,将用户重定向到CAS服务器。 2. CAS服务器收到重定向请求后,生成一个唯一的票据(ticket),并将该票据以重定向方式发送给用户的浏览器。 3. 用户的浏览器将携带票据重定向回原先的应用系统。 4. 应用系统接收到票据后,将该票据发送给CAS服务器进行验证。 5. CAS服务器验证票据的有效性,如果票据有效,则返回用户的登录凭证给应用系统。 6. 应用系统使用该凭证进行用户的登录操作,并为用户生成相应的会话信息。 7. 用户可以在该应用系统中进行操作,直到会话过期或用户主动注销。 8. 如果用户访问其他需要进行认证的应用系统,重复以上步骤2-7,但在步骤4中,CAS服务器验证票据的有效性后直接返回凭证给应用系统,无需用户再次登录。 通过CAS方式实现单点登录可以实现用户的统一认证和授权管理,提高用户的使用便捷性和体验度。CAS还可以支持多种认证方式,如用户名/密码、证书、短信验证码等,以满足不同应用系统的需求。此外,CAS还提供了管理中心,可以对用户进行集中管理和授权管理,提供更灵活的权限控制和用户管理功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值