单系统登录机制
1、http无状态协议
web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关联,这个过程用下图说明,三次请求/响应对之间没有任何联系
但这也同时意味着,任何用户都能通过浏览器访问服务器资源,如果想保护服务器的某些资源,必须限制浏览器请求;要限制浏览器请求,必须鉴别浏览器请求,响应合法请求,忽略非法请求;要鉴别浏览器请求,必须清楚浏览器请求状态。既然http协议无状态,那就让服务器和浏览器共同维护一个状态吧!这就是会话机制
2、会话机制
浏览器第一次请求服务器,服务器创建一个会话,并将会话的id作为响应的一部分发送给浏览器,浏览器存储会话id,并在后续第二次和第三次请求中带上会话id,服务器取得请求中的会话id就知道是不是同一个用户了,这个过程用下图说明,后续请求与第一次请求产生了关联
服务器在内存中保存会话对象,浏览器怎么保存会话id呢?你可能会想到两种方式
- 请求参数
- cookie
将会话id作为每一个请求的参数,服务器接收请求自然能解析参数获得会话id,并借此判断是否来自同一会话,很明显,这种方式不靠谱。那就浏览器自己来维护这个会话id吧,每次发送http请求时浏览器自动发送会话id,cookie机制正好用来做这件事。cookie是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,浏览器发送http请求时自动附带cookie信息
tomcat会话机制当然也实现了cookie,访问tomcat服务器时,浏览器中可以看到一个名为“JSESSIONID”的cookie,这就是tomcat会话机制维护的会话id,使用了cookie的请求响应过程如下图
3、登录状态
有了会话机制,登录状态就好明白了,我们假设浏览器第一次请求服务器需要输入用户名与密码验证身份,服务器拿到用户名密码去数据库比对,正确的话说明当前持有这个会话的用户是合法用户,应该将这个会话标记为“已授权”或者“已登录”等等之类的状态,既然是会话的状态,自然要保存在会话对象中,tomcat在会话对象中设置登录状态如下
1
2
|
|
用户再次访问时,tomcat在会话对象中查看登录状态
1
2
|
|
实现了登录状态的浏览器请求服务器模型如下图描述
每次请求受保护资源时都会检查会话对象中的登录状态,只有 isLogin=true 的会话才能访问,登录机制因此而实现。
二、多系统的复杂性
web系统早已从久远的单系统发展成为如今由多系统组成的应用群,面对如此众多的系统,用户难道要一个一个登录、然后一个一个注销吗?就像下图描述的这样
web系统由单系统发展成多系统组成的应用群,复杂性应该由系统内部承担,而不是用户。无论web系统内部多么复杂,对用户而言,都是一个统一的整体,也就是说,用户访问web系统的整个应用群与访问单个系统一样,登录/注销只要一次就够了
虽然单系统的登录解决方案很完美,但对于多系统应用群已经不再适用了,为什么呢?
单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器与服务器之间维护会话状态。但cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie
既然这样,为什么不将web应用群中所有子系统的域名统一在一个顶级域名下,例如“*.baidu.com”,然后将它们的cookie域设置为“baidu.com”,这种做法理论上是可以的,甚至早期很多多系统登录就采用这种同域名共享cookie的方式。
然而,可行并不代表好,共享cookie的方式存在众多局限。首先,应用群域名得统一;其次,应用群各系统使用的技术(至少是web服务器)要相同,不然cookie的key值(tomcat为JSESSIONID)不同,无法维持会话,共享cookie的方式是无法实现跨语言技术平台登录的,比如java、php、.net系统之间;第三,cookie本身不安全。
因此,我们需要一种全新的登录方式来实现多系统应用群的登录,这就是单点登录
三、单点登录
什么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分
1、登录
相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理,用下图说明
下面对上图简要描述
- 用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
- sso认证中心发现用户未登录,将用户引导至登录页面
- 用户输入用户名密码提交登录申请
- sso认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话,同时创建授权令牌
- sso认证中心带着令牌跳转会最初的请求地址(系统1)
- 系统1拿到令牌,去sso认证中心校验令牌是否有效
- sso认证中心校验令牌,返回有效,注册系统1
- 系统1使用该令牌创建与用户的会话,称为局部会话,返回受保护资源
- 用户访问系统2的受保护资源
- 系统2发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
- sso认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
- 系统2拿到令牌,去sso认证中心校验令牌是否有效
- sso认证中心校验令牌,返回有效,注册系统2
- 系统2使用该令牌创建与用户的局部会话,返回受保护资源
用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心,全局会话与局部会话有如下约束关系
- 局部会话存在,全局会话一定存在
- 全局会话存在,局部会话不一定存在
- 全局会话销毁,局部会话必须销毁
你可以通过博客园、百度、csdn、淘宝等网站的登录过程加深对单点登录的理解,注意观察登录过程中的跳转url与参数
2、注销
单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明
sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作
下面对上图简要说明
- 用户向系统1发起注销请求
- 系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求
- sso认证中心校验令牌有效,销毁全局会话,同时取出所有用此令牌注册的系统地址
- sso认证中心向所有注册系统发起注销请求
- 各注册系统接收sso认证中心的注销请求,销毁局部会话
- sso认证中心引导用户至登录页面
四、部署图
单点登录涉及sso认证中心与众子系统,子系统与sso认证中心需要通信以交换令牌、校验令牌及发起注销请求,因而子系统必须集成sso的客户端,sso认证中心则是sso服务端,整个单点登录过程实质是sso客户端与服务端通信的过程,用下图描述
sso认证中心与sso客户端通信方式有多种,这里以简单好用的httpClient为例,web service、rpc、restful api都可以
五、实现
只是简要介绍下基于java的实现过程,不提供完整源码,明白了原理,我相信你们可以自己实现。sso采用客户端/服务端架构,我们先看sso-client与sso-server要实现的功能(下面:sso认证中心=sso-server)
sso-client
- 拦截子系统未登录用户请求,跳转至sso认证中心
- 接收并存储sso认证中心发送的令牌
- 与sso-server通信,校验令牌的有效性
- 建立局部会话
- 拦截用户注销请求,向sso认证中心发送注销请求
- 接收sso认证中心发出的注销请求,销毁局部会话
sso-server
- 验证用户的登录信息
- 创建全局会话
- 创建授权令牌
- 与sso-client通信发送令牌
- 校验sso-client令牌有效性
- 系统注册
- 接收sso-client注销请求,注销所有会话
接下来,我们按照原理来一步步实现sso吧!
1、sso-client拦截未登录请求
java拦截请求的方式有servlet、filter、listener三种方式,我们采用filter。在sso-client中新建LoginFilter.java类并实现Filter接口,在doFilter()方法中加入对未登录用户的拦截
1
2
3
4
5
6
7
8
9
10
11
12
|
|
2、sso-server拦截未登录请求
拦截从sso-client跳转至sso认证中心的未登录请求,跳转至登录页面,这个过程与sso-client完全一样
3、sso-server验证用户登录信息
用户在登录页面输入用户名密码,请求登录,sso认证中心校验用户信息,校验成功,将会话状态标记为“已登录”
1
2
3
4
5
6
|
|
4、sso-server创建授权令牌
授权令牌是一串随机字符,以什么样的方式生成都没有关系,只要不重复、不易伪造即可,下面是一个例子
1
|
|
5、sso-client取得令牌并校验
sso认证中心登录后,跳转回子系统并附上令牌,子系统(sso-client)取得令牌,然后去sso认证中心校验,在LoginFilter.java的doFilter()中添加几行
1
2
3
4
5
6
7
8
9
10
11
|
|
verify()方法使用httpClient实现,这里仅简略介绍,httpClient详细使用方法请参考官方文档
1
2
|
|
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,添加几行
1
2
3
|
|
sso-client还需将当前会话id与令牌绑定,表示这个会话的登录状态与令牌相关,此关系可以用java的hashmap保存,保存的数据用来处理sso认证中心发来的注销请求
8、注销过程
用户向子系统发送带有“logout”参数的请求(注销请求),sso-client拦截器拦截该请求,向sso认证中心发起注销请求
1
2
3
4
|
|
sso认证中心也用同样的方式识别出sso-client的请求是注销请求(带有“logout”参数),sso认证中心注销全局会话
1
2
3
4
5
6
7
8
|
|
sso认证中心有一个全局会话的监听器,一旦全局会话注销,将通知所有注册系统注销
1
2
3
4
5
6
7
8
|
|
1.1服务端配置
1.1.1环境说明
- Windows10 64位
- jdk1.8.0_05
- apache-tomcat-8.0.47-windows-x64
- 会使用到的:cas-server-webapp-4.0.0.war、cas-client-core-3.2.1.jar、commons-logging、cas-server-support-jdbc-4.0.0.jar
- 确保本地jdk环境已经搭建好
1.1.2修改hosts文件
由于在本地测试的时候,服务端和客户端默认的ip地址都是127.0.0.1,为了方便区分,所以需要为了服务端和客户端配置不同的域名加以区分。
编辑文件 C:\Windows\System32\drivers\etc\hosts 在文件末端添加下面两条信息:
- server.jix.com =>> 对应部署cas server的tomcat,这个虚拟域名还用于服务端证书生成
- client1.jix.com =>> 对应部署client1客户端应用的tomcat
- client2.jix.com =>> 对应部署client2客户端应用的tomcat
【由于CAS是基于HTTPS协议,所以需要配置服务端的tomcat,使之支持SSL安全协议访问】
1.1.3配置https协议(安全证书配置)
1.打开cmd命令窗口
2.生成证书,在cmd窗口输入以下命令:
keytool -genkey -alias ssodemo -keyalg RSA -keysize 1024 -keypass jixsso -validity 365 -keystore F:\jix\sso.keystore -storepass jixsso
[说明]:-alias后面的别名可以自定义,-keypass指定证书密钥库的密码, -storepass和前面keypass密码相同,否则下面tomcat 配置https 会访问失败 -keystore指定证书的位置,这里指定放在F盘的jix目录,密钥库名称可以自定义..这里是jixsso.keystore
3.命令输入完成,回车之后,会提示你输入一些资料,见下图:
证书命令图2.1
【
注意
】:第一个让你输入的“您的名字与姓氏是什么”,请必须输入在C:\Windows\System32\drivers\etc\hosts文件中加入的服务端的域名.我这里也就是server.jix.com,为何这么做?首先cas只能通过域名来访问,不能通过ip访问,同时上方是生成证书,所以要求比较严格,所以如果不这么做的话,在完成最终配置之后,cas也可以正常访问,访问一个客户端应用虽然能进入cas验证首页,但是,当输入信息正确后,cas在回调转入你想访问的客户端应用的时候,会出现
No subject alternative names present
错误异常信息
,这个错误也就是在上面输入的第一个问题答案不是域名导致、或者与hosts文件配置的不一致导致
。
4.导出证书:
在cmd窗口继续输入以下命令,导出证书
keytool -export -alias ssodemo -keystore F:\jix\sso.keystore -file F:\jix\sso.crt -storepass jixsso
【说明】:-alias后面的名称要与生成证书的命令里面的alias的名称一致. –keystore后面指定证书存放的位置,这里我放在F盘jix目录,同时证书名称要与【生成证书】对应的命令里的keystore名称一致.这里是sso.keystore,-file后面才crt路径,我也指定在F盘jix目录. –storepass的证书密码要与上面输入的密码一致.
如下图所示:
证书命令图2.2
下面是F盘jix目录下生成的crt文件:
证书位置图2.3
5.客户端导入证书
在cmd窗口输入命令 (以管理员方式运行)
keytool -import -keystore "%JAVA_HOME%\../jre8\lib\security\cacerts" -file F:\jix\sso.crt -alias ssodemo3
【说明】:-file指定证书的位置,也就是上一步导出证书的位置,即F:\jix\sso.crt 命令中指定了JAVA_HOME,意思是将证书导入到客户端证书库,也就是jdk证书库中.因为客户端应用运行在本地,需要jdk的支持。
回车之后,会让你输入密钥库口令,注意,这里的密码必须要输入changeit,不能输入上面指定的密码jixsso,切记,否则导入客户端证书会有问题,如果是多台机器演示,需要在每一台客户端导入该证书,步骤都是一样的。当看到提示“是否信任此证书”,输入y回车即可,见下图:(说明,命令中的-alias后面的别名可以自定义,如果出现【证书未导入,别名<***>已经存在】的错误,该意思是说客户端的密钥库中已经存在该别名证书了,重新指定其他别名即可.
证书命令图2.4
点击回车可以看到证书已添加到秘钥库中
至此,CAS所需的证书环境,已经配置好。
下面,开始我们的CAS服务、Tomcat、以及多客户端的配置及测试访问。
1.1.4部署CAS-Server相关的Tomcat
1. 配置HTTPS
解压apache-tomcat-8.0.47-windows-x64.zip,我本地路径为E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server,编辑E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\conf\server.xml,找到下面片段:
<!–
<Connector executor=”tomcatThreadPool”
port=”8080″ protocol=”HTTP/1.1″
connectionTimeout=”20000″
redirectPort=”8443″ />
–>
去掉注释,修改成:
<Connector port=”8443″ protocol=”org.apache.coyote.http11.Http11Protocol”
maxThreads=”150″ SSLEnabled=”true” scheme=”https” secure=”true”
keystoreFile=” F:\jix\sso.keystore ” keystorePass=”jixsso”
clientAuth=”false” sslProtocol=”TLS” />
其中,keystoreFile就是创建证书的路径,keystorePass就是创建证书的密码
2. 验证HTTPS配置
其他按照默认配置不作修改,双击E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\bin\startup.bat启动tomcat 验证https是否配置成功,我本地使用谷歌浏览器访问,在地址栏输入
https://server.jix.com:8443/出现下面画面,其实这就表明cas服务端tomcat的https配置是没有问题了.
服务端登录图2.5
点击高级,然后继续访问,将会出现下面tomcat默认首页.tomcat已经支持https协议访问了,一切ok!
Tomcat页面图2.7
3. 部署CAS-Server
CAS-Server 下载地址:
http://www.jasig.org/cas/download
本文以cas-server-webapp-4.0.0.rar为例,解压提取cas-server-webapp-4.0.0.war文件,把改文件copy到E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\webapps目下,并重命名为:cas.war.
启动tomcat,在浏览器地址栏输入:https://server.jix.com:8443/cas ,回车,出现CAS服务端的登录验证首页:
Cas登录图2.8
【说明】:此时,CAS只是单独运行,至于登录的用户名和密码是什么,请查看:
E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\webapps\cas\WEB-INF\deployerConfigContext.xml文件中有这样一段
配置:
<beanid=”primaryAuthenticationHandler”
class=”org.jasig.cas.authentication.AcceptUsersAuthenticationHandler”>
<property name=”users”>
<map>
<entry key=”casuser” value=”Mellon”/>
</map>
</property>
</bean>
这个配置是默认静态配置用户名和密码,那就在浏览器的CAS服务的登陆框中输入用户名casuser和密码Mellon,登录看看效果,就会出现验证成功的页面,如下图。你也可以在文件中自己配置自己的用户名和密码。
登录成功图2.9
看到上述页面表示CAS-Server已经部署成功。
1.1.5 CAS与数据库交互
【说明】:我本地使用的是oracle数据库。
1、,需要将几个jar文件,放到CAS服务的lib目录下,我本地使用的jar版本分别是commons-dbcp-1.2.1.jar、commons-pool.jar、cas-server-support-jdbc-4.0.0.jar、ojdbc6.jar,这4个缺一不可。将这4个jar放到E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\webapps\cas\WEB-INF\lib目录下。
2、修改配置,支持mysql数据库交互验证
编辑E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server\webapps\cas\WEB-INF\ deployerConfigContext.xml文件,你会看到有这样一段配置:
Cas服务端配置图2.10
注释掉第二个entry配置,最终配置如下:
<constructor-arg>
<map>
<entrykey-ref=”proxyAuthenticationHandler”value-ref=”proxyPrincipalResolver” />
<!– 注释这个–>
<!–<entrykey-ref=”primaryAuthenticationHandler”value-ref=”primaryPrincipalResolver” />–>
<!– key-ref指定自己的本地数据库访问 –>
<entry key-ref=”dbAuthHandler”value-ref=”primaryPrincipalResolver”/>
</map>
</constructor-arg>
上述配置截图:
Cas服务端配置图2.11
然后再在这个xml中新加入2个bean配置,如下:
<!– 指定dbcp数据源–>
<bean id=”dataSource” class=”org.apache.commons.dbcp.BasicDataSource”>
<property name=”driverClassName”value=”oracle.jdbc.driver.OracleDriver”></property>
<property name=”url” value=”jdbc:oracle:thin:@10.65.106.71:1521:orcl”></property>
<property name=”username” value=”dass_up”></property>
<property name=”password” value=”123″></property>
</bean>
<!– 访问远程数据库 –>
<beanid=”dbAuthHandler”class=”org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler”>
<property name=”dataSource”ref=”dataSource”></property>
<property name=”sql”value=”select password fromt_system_user where username=?”></property>
</bean>
要说明的是,红色标注的内容,我想大家都能看的明白,就是指定数据库驱动和连接信息。其中,sql语句的意思就是,根据用户名获取密码,CAS会根据你页面输入的用户名获取该用户密码,和你输入的密码进行校验,来判断输入是否正确。Sql中的表换成远程数据库的表即可。只要根据用户名查询密码即可。
以上配置截图:
Cas服务端配置图2.12
至此,CAS与数据库交互验证的配置已经配置完成
,你可以重新访问cas,输入数据库中存在的用户名和密码,来看看效果如何~如果登录成功,说明配置无误。否则,请耐心检查配置是否有问题,jar包是否缺少。
现在,CAS已经支持数据库交互验证了,服务端tomcat也支持HTTPS协议访问,现在,我们来搭建客户端,实现多个客户端的单点登录。这里,我本地只使用2个tomcat客户端来测试,其实已经满足单点登录的要求了,至少2个应用。
1.2 CAS客户端配置
1.2.1 部署CAS客户端相关的Tomcat
首先,客户端应用是要和CAS服务端进行交互的,所以这里需要jar文件,放在客户端应用的lib目录下。分别是:cas-client-core-3.2.1.jar、commons-logging.jar
这里呢,我就直接使用tomcat默认自带的 webapps\examples 作为测试的简单web项目。我就不去另写一个web测试的demo了。
既然需要2个客户端应用,则需要2个tomcat做为客户端服务器,所以,我本地解压了2份tomcat,作为客户端服务器,并重新命名,本地路径分别为:E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47- client1和E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47– client2
首先,将上面2个jar分别放到E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47- client1\webapps\examples\WEB-INF\lib目录
和E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47– client2\webapps\examples\WEB-INF\lib目录
1、 配置apache-tomcat-7.0.57-client1客户端1:
修改tomcat的启动端口:
编辑E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47- client1\conf\server.xml文件,找到如下2处内容:
<Connector port=”8080″protocol=”HTTP/1.1″
connectionTimeout=”20000″
redirectPort=”8443″ />
这里请将port=”8080″修改成其他4位端口,不能和CAS服务端的tomcat相同,否则,在同一台机器上测试会出现端口占用的错误,我修改成18080,如果是在不同的机器上,则不需要配置这些。
<Connector port=”8009″protocol=”AJP/1.3″ redirectPort=”8443″ />
这里请将port=”8009″修改成其他4位端口,不能和CAS服务端相同.我修改成18009
好,启动这个tomcat,即运行E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47- client1\bin\startup.bat,如果启动窗口中没有出现错误,说明端口配置无误。请记住你配置的端口号。浏览器输入
http://client1.jix.com:18080/examples/servlets/
,请注意红色部分域名,就是本文档一开始需要配置的C:\Windows\System32\drivers\etc\hosts的域名,用于不同的客户端域名访问,回车:
客户端登录图2.13
看到上述界面表示apache-tomcat-8.0.47- client1的基本安装配置已经成功。
接下来需要配置最重要的内容,让客户端应用和CAS服务连接:
编辑E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47- client1\webapps\examples\WEB-INF\web.xml,在最下面加入如下配置:
<!– 用于单点退出,该过滤器用于实现单点登出功能,可选配置–>
<listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!–该过滤器用于实现单点登出功能,可选配置 –>
<filter>
<filter-name>CAS Single Sign OutFilter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CASSingle Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://server.jix.com:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://client1.jix.com:18080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://server.jix.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://client1.jix.com:18080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
该过滤器负责实现HttpServletRequest请求的包裹,比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。
-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class> org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置完成后,启动CAS服务端tomcat,再启动该客户端1的tomcat,在浏览器访问:
http://client1.jix.com:18080/examples/servlets/servlet/HelloWorldExample
看看是否跳转到了CAS认证界面,回车之后,会出现如下图:
Cas服务端登录图2.14
由于你没有登录CAS认证系统,CAS认证系统拦截到你访问的客户端应用,首先进入到认证系统登录界面,同时URL后面加上你想访问的地址信息,当你登录成功后,CAS服务会转向到你刚刚访问的地址,也就是
http://client1.jix.com:18080/examples/servlets/servlet/HelloWorldExample
转向到这个地址之后,浏览器会显示如下内容:
客户端验证成功图2.15
上面这个内容,显示的就是你访问tomcat中的examples项目的一个servlet的返回结果。
这里,你会发现浏览器地址栏多了一个内容,即多了一个jsessionid参数,这个就是CAS认证的原理所在,使用的是COOKIE机制。
1.2.2 配置CAS客户端2
配置与上面的客户端配置步骤相同,其中需要注意的就是,这第二个客户端的tomcat端口要与上面的客户端和CAS服务端的端口要不一样,否则出现端口占用的错误。
主要配置如下:
客户端配置图2.16
Port修改成28080
Port修改成28009
修改编辑E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47 – client2\webapps\examples\WEB-INF\web.xml文件,加入的内容就是上面在第一个客户端的web.xml内容一致,只不过需要修改2处内容,就是几个url地址, 最终的配置如下:
<!– 用于单点退出,该过滤器用于实现单点登出功能,可选配置–>
<listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!– 该过滤器用于实现单点登出功能,可选配置 –>
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CAS Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://server.jix.com:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://client2.jix.com:28080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://server.jix.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://client2.jix.com:28080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
该过滤器负责实现HttpServletRequest请求的包裹,比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。
-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class> org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.2.3 测试验证SSO
至此,2个客户端也已经配置完毕,启动配置好的三个tomcat分别为:CAS服务端tomcat、2个客户端tomcat
我本地路径分别为:
服务端tomcat:E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47-server
客户端1:E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47 – client1
客户端2:E:\Tomcat-anzhuangbao\apache-tomcat-8.0.47-windows-x64\apache-tomcat-8.0.47 – client2
访问客户端1—-> 跳转到cas server 验证 —-> 显示客户端1的应用 —->新开选项卡访问客户端2 —-> 显示客户端2应用 —-> 注销cas server —-> 打开客户端1/客户端2 —-> 重新跳转到cas server 验证.
下面截图,根据上面所示进行测试,看看是否与上面说的流程一致:
首先,打开谷歌浏览器,地址栏输入:
http://client1.jix.com:18080/examples/servlets/servlet/HelloWorldExample
回车,将会出现CAS认证界面:
服务端登录图2.17
输入用户名和密码,登录成功后,显示的界面:
客户端1登录成功图2.18
重新打开一个选项卡,地址栏输入
http://client2.jix.com:28080/examples/servlets/servlet/HelloWorldExample
回车,将直接显示客户端2界面,没有重新登录,浏览器显示界面:
客户端2登录图2.19
根据上面显示的界面,按照普通想逻辑,当访问客户端2的时候,应该会被CAS拦截,转到CAS认证服务的界面,但是结果却直接显示客户端2的界面,原因就是因为你在访问客户端1的时候已经登录认证过了,CAS会在你浏览器中注入COOKIE,记录你的认证凭证,如果你的浏览器没有关闭或者退出的话,当你访问客户端2应用的时候,CAS检测到认证的凭证,所以,就直接显示了客户端2的界面。
这里,其实就已经说明,CAS单点登录系统已经搭建完毕!运行一切正常!
下面,我们新打开一个选项卡(也可在当前页面的地址栏输入),在浏览器地址栏中输入
https://server.jix.com:8443/cas/logout
回车显示:
Cas退出成功图2.20
上述表示 认证注销成功,此时如果再访问 :
http://client1.jix.com:18080/examples/servlets/servlet/HelloWorldExample
或
http://client2.jix.com:28080/examples/servlets/servlet/HelloWorldExample
都将会跳转到CAS服务重新进行认证。
到此,SSO之CAS单点登录系统已经搭建完毕!