单点登录CAS

1.0、SSO概念

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO 并不能算是一种架构,只能说是一个解决方案。SSO核心意义就一句话:一处登录,处处登录;一处注销,处处注销。就是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统,即用户只需要记住一组用户名和密码就可以登录所有有权限的系统。

1.1、Cookie单点登录
单点登录的实现方案,一般就包含以下三种:

  • Cookies
  • Session同步
  • Session同步

目前的大型网站都是采用分布式Session的方式。我先从cookie的实现谈起,你就能很清楚的知道为什么需要分布式session方式实现单点登录。

基于Cookie的单点登录
最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。 用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。

不难发现以上方式把信任存储在客户端的Cookie中,这种方式很容易令人质疑:
Cookie不安全
不能跨域实现免登

对于第一个问题,通过加密Cookie可以保证安全性,当然这是在源代码不泄露的前提下。如果Cookie的加密算法泄露,攻击者通过伪造Cookie则可以伪造特定用户身份,这是很危险的。
对于第二个问题,不能跨域实现免登更是硬伤。所以,才有了以下的分布式session方案。

1.2、分布式session单点登录
例如,阿里有很多系统分割为多个子系统,独立部署后,不可避免的会遇到会话管理的问题,类似这样的电商网站一般采用分布式Session实现。

再进一步可以根据分布式Session+redis,建立完善的单点登录或账户管理系统。

流程运行:

  1. 用户第一次登录时,将会话信息(用户Id和用户信息),比如以用户Id为Key,写入分布式
    Session;
  2. 用户再次登录时,获取分布式Session,是否有会话信息,如果没有则调到登录页;
  3. 一般采用Cache中间件实现,建议使用Redis,因此它有持久化功能,方便分布式Session宕机后,
    可以从持久化存储中加载会话信息;
  4. 存入会话时,可以设置会话保持的时间,比如15分钟,超过后自动超时;
    结合Cache中间件实现的分布式Session,可以很好的模拟Session会话。

===================================================================================
1.3、常见方案
实现单点登录说到底就是要解决如何产生和存储那个信任,再就是其他系统如何验证这个信任的有效性,因此要点也就以下两个:
存储信任 服务器生产
验证信任 ~ 拿到服务器再次验证~

单点登录的常见落地实现技术有哪些?
身份认证技术:

  1. cas(单点登录)
  2. Spring Security OAuth2(第三方登录授权:QQ登陆)
  3. jwt (客户端token:原生)
    安全控制框架:
  4. spring-security
  5. shiro:

1.3.1、cas(单点登录流程图)
单点登录CAS_第1张图片

解决问题:多个系统只需登录一次,无需重复登录

原理:授权服务器,被授权客户端 CS架构

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

缺点:cas单点登录技术适用于传统应用的场景比较多, 官方示例也是以javaWeb为准, 对微服务化应用,前后端分离应用,支持性较差。

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

OAuth2是用来允许用户授权第三方应用访问他在另一个服务器上的资源的一种协议,它不是用来做单点登录的,但我们可以利用它来实现单点登录。

原理:主系统,授权系统(给主系统授权用的,也可以跟主系统是同一个系统),第三方系统。

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

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

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

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

1.3.5、Shiro
Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。

以下是 Apache Shiro 可以做的事情:

  1. 验证用户来核实他们的身份
  2. 对用户执行访问控制
  3. 判断用户是否被分配了一个确定的安全角色
  4. 判断用户是否被允许做某事
  5. 在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。
  6. 在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。
  7. 聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。
  8. 启用单点登录(SSO)功能。内置了jasig-cas
  9. 为没有关联到登录的用户启用"Remember Me"服务。

1.4、市面主流的技术搭配
单点登录CAS_第2张图片

2.0、CAS

2.0.1、介绍
CAS(Central Authentication Service) 是 Yale 大学发起的一个开源项目,是单点登录的一种现方式
HTTPS http
官网地址:https://www.apereo.org/
开源的CAS的Gitee地址:https://gitee.com/original-intention/cas.git
自定义的CAS服务器Gitee地址:https://gitee.com/original-intention/sso-server.git

分为CAS Server服务端和CAS Client客户端:

CAS Server:
CAS Server 负责完成对用户的认证工作, CAS Server 需要独立部署,有不止一种 CAS Server 的实
现, Yale CAS Server 和 ESUP CAS Server 都是很不错的选择。CAS Server 会处理用户名 / 密码等凭证
(Credentials) ,它可能会到数据库检索一条用户帐号信息,也可能在 XML 文件中检索用户密码,对这
种方式, CAS 均提供一种灵活但同一的接口 / 实现分离的方式, CAS 究竟是用何种认证方式,跟 CAS
协议是分离的,也就是,这个认证的实现细节可以自己定制和扩展.

CAS Client:
CAS Client 负责部署在客户端(注意,我是指 Web 应用),原则上, CAS Client 的部署意味着,当
有对本地 Web 应用的受保护资源的访问请求,并且需要对请求方进行身份认证, Web 应用不再接受任
何的用户名密码等类似的 Credentials ,而是重定向到 CAS Server进行认证。目前, CAS Client 支持
(某些在完善中)非常多的客户端,包括 Java 、 .Net 、 ISAPI 、 Php 、 Perl 、 uPortal 、 Acegi 、
Ruby 、VBScript 等客户端,几乎可以这样说, CAS 协议能够适合任何语言编写的客户端应用。

2.0.2、配置https
CAS Server默认使用HTTPS进行访问,并要求我们提供一个密码库—(利用tomcat服务器配置https双向认证)
步骤:

  1. 生成服务器的密匙文件tomcat.keystore
  2. 命令:

生成密钥

keytool -genkey -alias cyh -keyalg RSA -keysize 2048 -validity 36500 -keystore C:/keys/cyh.keystore
3. 参数说明:
-genkey 生成密钥
-alias 指定别名,这里是icoding
-keyalg 指定密钥算法,这时指定RSA,
-keysize 指定密钥长度,默认是1024,这里指定2048,长一点,比较难破解,
-validity 指定证书有效期,这里指定36500.
-keystore 指定密钥库存储位置,这里存在 D:/keys/目录下

注意:您的名字与姓氏www.sso.com是CAS服务器使用的域名,不是随便乱定的,其他的随意.

  1. 导出证书
keytool -export -alias cyh -storepass 123456 -file C:/keys/cyh.cer -keystore C:/keys/cyh.keystore
  1. 参数说明
-alias指定别名为icoding ;
-storepass指定私钥为123456;
-file指定导出证书的文件名为icoding.cer;
-keystore指定之前生成的密钥文件的文件名。
注意:-alias和-storepass必须为生成icoding .keystore密钥文件时所指定的别名和密码,否则证书导出失败.
  1. 导入证书导入到jdk信任库
keytool -import -alias cyh -keystore  C:/Progra~1/Java/jre1.8.0_181/lib/security/cacerts -file C:/keys/cyh.cer 
 -trustcacerts


 
 #注意:
# 1.原来的$JAVA_HOME/jre/lib/security/cacerts文件要先删掉,否则会报出
# java.io.IOException: Keystore was tampered with, or password was incorrect
错误.
# 2.如果路径有空格或特殊字符,加上引号.

2.0.3 springboot集成CAS

1.导入cas依赖

<dependency>
    <groupId>net.unicon.cas</groupId>
    <artifactId>cas-client-autoconfig-support</artifactId>
    <version>2.3.0-GA</version>
</dependency>

2.配置cas

#填CAS服务器的前缀
cas.server-url-prefix=https://www.sso.com:8443/cas
#填CAS服务器的登录地址
cas.server-login-url=https://www.sso.com:8443/cas/login
#填客户端的访问前缀
cas.client-host-url=http://www.tb.com:8010

代码的远程Gitee地址:https://gitee.com/original-intention/cas-springboot.git

3.0.0Spring Security集成CAS

Spring Security提供了一个独立的依赖包来实现CAS Client,我们只需在pom.xml文件中声明引入即可。

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-cas</artifactId>
</dependency>

CAS Client的相关配置信息

#CAS Server主路径
cas.server.prefix=https://cas.chenmuxin.cn:8443/cas
#CAS Server登录URL
cas.server.login=${cas.server.prefix}/login
#CAS Server注销URL
cas.server.logout=${cas.server.prefix}/logout

#CAS Client主路径
cas.client.prefix=http://client.cas.chenmuxin.cn:8080
#CAS Client登录URL
cas.client.login=${cas.client.prefix}/login/cas
#CAS Client注销URL的相对路径形式
cas.client.logout.relative=/logout/cas
#CAS Client注销URL的绝对路径形式
cas.client.logout=${cas.client.prefix}${cas.client.logout.relative}

#CAS Server的登录用户名
cas.user.inmemory=zhangsan

代码的gitee远程地址:https://gitee.com/original-intention/spring-security-cas.git

你可能感兴趣的:(Spring,Security,安全,spring,java)