zoukankan      html  css  js  c++  java
  • 【单点登录学习之一】深刻认识单点登录

    一、单系统登录机制
    1、http无状态协议
    (1)web应用采用B/S架构,http作为通信协议。
    (2)http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关联。

    2、会话机制
    (1)只要能上网的终端设备都能向这个WEB应用资源发起http请求,而如果想保护服务器的某些资源,必须限制浏览器请求;
    要限制浏览器请求,必须鉴别浏览器请求,响应合法请求,忽略非法请求;
    要鉴别浏览器请求,必须清楚浏览器请求状态;
    既然http协议无状态,那就让服务器和浏览器共同维护一个状态吧!这就是会话机制。

    (2)浏览器第一次请求服务器,服务器创建一个会话,并将会话的id作为响应的一部分发送给浏览器,浏览器存储会话id,
    并在后续第二次和第三次请求中带上会话id,服务器取得请求中的会话id就知道是不是同一个用户了,
    这样后续请求与第一次请求产生了关联。

    (3)服务器在内存中保存会话对象,浏览器怎么保存会话id呢?你可能会想到两种方式:请求参数和cookie。
    将会话id作为每一个请求的参数,服务器接收请求自然能解析参数获得会话id,并借此判断是否来自同一会话,很明显,这种方式不靠谱。
    那就浏览器自己来维护这个会话id吧,每次发送http请求时浏览器自动发送会话id,cookie机制正好用来做这件事。
    cookie是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,浏览器发送http请求时自动附带cookie信息
    tomcat会话机制当然也实现了cookie,访问tomcat服务器时,浏览器中可以看到一个名为“JSESSIONID”的cookie,这就是tomcat会话机制维护的会话id。

    3、登录状态
    我们假设浏览器第一次请求服务器需要输入用户名与密码验证身份,服务器拿到用户名密码去数据库比对,正确的话说明当前持有这个会话的用户是合法用户,应该将这个会话标记为“已授权”或者“已登录”等等之类的状态,既然是会话的状态,自然要保存在会话对象中,tomcat在会话对象中设置登录状态如下

    HttpSession session = request.getSession();
    session.setAttribute("isLogin", true);

    用户再次访问时,tomcat在会话对象中查看登录状态

    HttpSession session = request.getSession();
    session.getAttribute("isLogin");

    每次请求受保护资源时都会检查会话对象中的登录状态,只有 isLogin=true 的会话才能访问,登录机制因此而实现。

    实现了登录状态的浏览器请求服务器模型如下图:

    小结:
    单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器与服务器之间维护会话状态。但cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie。

    二、多系统登录
    1、同域多系统登录

    1.1、场景
    (1)一个域名一个应用,这个应用有多个机器节点组成集群;
    (2)同一个顶级域名,多个二级域名系统或者同一个应用多个节点组成的集群

    具体示例:
    一级域名:baidu.com;
    二级域名:百度百科baike.baidu.com、百度新闻news.baidu.com、百度知道zhidao.baidu.com等等;
    假设百度有一个专门用来登录的系统:sso.baidu.com

    1.2、同域多系统登录有两个问题需要解决
    (1)Cookie是不能跨域的,我们登录Cookie的domain属性是sso.baidu.com,在给baike.baidu.com、news.baidu.com、zhidao.baidu.com发送请求是带不上的;
    (2)sso、baike、news、zhidao是不同的应用,它们的session存在自己的应用内,是不共享的;

    1.3、解决方案
    有两种:
    (1)传统方案
    将cookie域设置为顶级域,解决cookie不能跨域的问题;
    将session会话保存在共享缓存(比如redis)里解决多个系统session共享的问题;

    (2)单点登录

    2、不同域多系统登录
    同域下多系统登录是巧用了Cookie顶域的特性。如果是不同域,不同域之间Cookie是不共享的,怎么办?就只能使用单点登录了。

    三、单点登录
    什么是单点登录
    单点登录(Single Sign On,简称SSO):是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分.

    1、登录
    (1)相比于单系统登录,sso需要一个独立的认证中心:
      只有认证中心能接受用户的用户名密码等安全信息;
      其他系统不提供登录入口,只接受认证中心的间接授权;
    间接授权通过令牌实现:
      sso认证中心验证用户的用户名密码没问题,创建授权令牌
      在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权;
      可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。
    这个过程,也就是单点登录的原理:

    (2)图示+描述

    (1)用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
    (2)sso认证中心发现用户未登录,将用户引导至登录页面
    (3)用户输入用户名密码提交登录申请
    (4)sso认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话,同时创建授权令牌
    (5)sso认证中心带着令牌跳转会最初的请求地址(系统1)
    (6)系统1拿到令牌,去sso认证中心校验令牌是否有效
    (7)sso认证中心校验令牌,返回有效,注册系统1
    (8)系统1使用该令牌创建与用户的会话,称为局部会话,返回受保护资源
    (9)用户访问系统2的受保护资源
    (10)系统2发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
    (11)sso认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
    (12)系统2拿到令牌,去sso认证中心校验令牌是否有效
    (13)sso认证中心校验令牌,返回有效,注册系统2
    (14)系统2使用该令牌创建与用户的局部会话,返回受保护资源

    (3)用户登录成功之后,会与sso认证中心及各个子系统建立会话,

    用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话;
    局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心;
    全局会话与局部会话有如下约束关系:
      (1)局部会话存在,全局会话一定存在;
      (2)全局会话存在,局部会话不一定存在;
      (3)全局会话销毁,局部会话必须销毁;

    2、注销
    单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁。
    sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作。

    (1)用户向系统1发起注销请求;
    (2)系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求;
    (3)sso认证中心校验令牌有效,销毁全局会话,同时取出所有用此令牌注册的系统地址;
    (4)sso认证中心向所有注册系统发起注销请求;
    (5)各注册系统接收sso认证中心的注销请求,销毁局部会话;
    (6)sso认证中心引导用户至登录页面;

    3、部署
    单点登录涉及sso认证中心与众子系统;
    子系统与sso认证中心需要通信以交换令牌、校验令牌及发起注销请求;
    因而子系统必须集成sso的客户端,sso认证中心则是sso服务端,整个单点登录过程实质是sso客户端与服务端通信的过程;
    sso认证中心与sso客户端通信方式有多种,这里以简单好用的httpClient为例,web service、rpc、restful api都可以;

    4、实现
    示例代码参考:simple-sso

    参考:
    单点登录(原理与实现简介)
    单点登录(SSO)

    四、单点登录技术选型

    1、CAS-单点登录
    CAS(Central Authentication Service),中央认证服务,一种独立开放指令协议。CAS是耶鲁大学(Yale University)发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法。
    1.1、解决问题:多个系统只需登录一次,无需重复登录

    1.2、原理:服务器用来授权,客户端用来被授权
    (1)授权服务器(一个)保存了全局的一份session,客户端(多个)各自保存自己的session
    (2)客户端登录时判断自己的session是否已登录,若未登录,则(告诉浏览器)重定向到授权服务器(参数带上自己的地址,用于回调)
    (3)授权服务器判断全局的session是否已登录,若未登录则定向到登录页面,提示用户登录,登录成功后,授权服务器重定向到客户端(参数带上ticket【一个凭证号】)
    (4)客户端收到ticket后,请求服务器获取用户信息
    (5)服务器同意客户端授权后,服务端保存用户信息至全局session,客户端将用户保存至本地session

    1.3、缺点
    (1)默认不支持http请求, 仅支持https
    (2)CAS单点登录技术适用于传统应用的场景比较多,官方示例也是以javaWeb为准,对微服务化应用,前后端分离应用,支持性较差

    2、OAUTH2-第三方登录授权
    2.1、解决问题:第三方系统访问主系统资源,用户无需将在主系统的账号告知第三方,只需通过主系统的授权,第三方就可使用主系统的资源。
    如:APP1需使用微信支付,微信支付会提示用户是否授权,用户授权后,APP1就可使用微信支付功能了

    2.2、原理:主系统,授权系统(给主系统授权用的,也可以跟主系统是同一个系统),第三方系统
    (1)第三方系统需要使用主系统的资源,第三方重定向到授权系统
    (2)根据不同的授权方式,授权系统提示用户授权
    (3)用户授权后,授权系统返回一个授权凭证(accessToken)给第三方系统【accessToken是有有效期的】
    (4)第三方使用accessToken访问主系统资源【accessToken失效后,第三方需重新请求授权系统,以获取新的accessToken】

    2.3、OAUTH2中的角色
    Resource Server: 被授权访问的资源
    Authotization Server:OAUTH2认证授权中心
    Resource owner : 资源拥有者
    Client:使用API的客户端(如Android 、IOS、web app)
    工作流程如下:

    3、JWT-客户端token
    Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该token被设计为紧凑且安全的,
    特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从
    资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
    基于JWT认证协议,自己开发SSO服务和权限控制。
    流程如下

     

    (二)安全控制框架
    1、spring-security
    spring-security是spring家族的安全控制框架, 功能非常完善,能够为J2EE项目提供综合性的安全访问控制解决方案的安全框架。
    它依赖于Servlet过滤器。这些过滤器拦截进入请求,并且在应用程序处理该请求之前进行某些安全处理。

    Spring Security对用户请求的拦截过程如下:

     

    2、shiro
    Apache Shiro是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。
    以下是你可以用 Apache Shiro 所做的事情:
    (1)验证用户来核实他们的身份
    (2)对用户执行访问控制,
      (2.1)判断用户是否被分配了一个确定的安全角色
      (2.2)判断用户是否被允许做某事
    (3)在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。
    (4)在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。
    (5)聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。
    (6)启用单点登录(SSO)功能。 内置了jasig-cas
    (7)为没有关联到登录的用户启用"Remember Me"服务

    (三)市面上一些主流的技术搭配

    spring-security + oauth2
    spring-security + cas
    spring-security + jwt
    shiro + cas

    对比:

    参考:

    单点登录SSO技术选型

  • 相关阅读:
    如何实现parseFloat保留小数点后2位
    C#正则表达式整理备忘
    HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案
    c# using的几种用法
    QQ截图 有快捷键的,如Shift+S
    史上最深刻的黄段子
    文本框回车自动提交
    C#与ASP.NET中DateTime.Now函数详解
    ASP.NET页面生命周期
    .NET中HttpWebRequest详解
  • 原文地址:https://www.cnblogs.com/cac2020/p/13716521.html
Copyright © 2011-2022 走看看