CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案
CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况。在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户session所在的具体客户应用服务器,而不是转发到其他集群服务器上,二是解决CAS服务端集群环境下各种Ticket信息的共享。
CAS集群部署
由于CAS Server是一个Web应用,因此可部署在Tomcat等容器中。直接部署CAS集群并使用负载均衡配置后,由于每次访问的CAS Server不固定,会发生通行证丢失。
解决方法:配置TOMCAT集群及Session复制,解决CAS Server Session复制。详细配置方法见"Nginx+Tomcat+Memcached集群"。
CAS的Ticket信息共享
当用户登录后,Ticket存储在CAS Server中,由于这部分数据未保存在Session中,仅靠TOMCAT Session复制无法解决问题。默认配置下,CAS Server使用org.jasig.cas.ticket.registry.DefaultTicketRegistry把Ticket数据保存在 HashMap中,因此多台CAS Server无法共享数据。导致用户登录及退出均存在问题。因此需要将Ticket信息进行共享存储,使多台CAS Server使用相同的存储区域管理Ticket。
Ticket信息共享处理比较简单,就是将Ticket信息从原来的内存存储变为数据库存储。见"ticketRegistry.xml"文件。处理方法有两种:1是将Ticket信息放在Redis内存数据库中,2是将Ticket信息放在memcached中,推荐使用memcached,现在DMGeoSSO已经支持这两种方式了,配置文件示例见"ticketRegistry.xml.redis"和ticketRegistry.xml.memcache。默认配置文件的内容为"ticketRegistry.xml.default"
Redis方式源代码:RedisTicketRegistry.java
Memcached方式源代码:MemCacheTicketRegistry.java
这里需要注意的是:TGT和ST的超时时间最大只能设置为30天(即2592000秒),多1秒都不行。这是Memcached的特性。
CAS单点注销
根据CAS Server工作流程,当收到Logout请求后,CAS Server会删除自身存储的有关当前用户的所有Ticket票据,"问题二"的解决方法已经解决了多台CAS Server删除票据的问题。但随后从CAS Server会发起HTTP POST请求到应用服务器,该请求中具备"logoutRequest"标志,应用服务器的SingleSignOutFilter接收到该请求后在应用服务器端进行用户登出操作。该操作主要是将应用服务器端的CAS Client中保存的用户Session数据失效,达到客户端登出效果。即,对于CAS系统,必须Server端和Client均进行登出操作,用户才会真正登出。cas退出采用的是异步操作,客户端是否退出成功也不关心。
CAS Server的这个工作流程,在应用集群部署的情况下带来一系列问题。由于应用服务器集群化,且一般会使用Session复制,当CAS Server向应用服务器发起Logout请求时,仅针对一台服务器发起请求,导致应用服务器没有全部退出,使得用户使用登出操作时,有时可以退出,有时不能退出,用户体验很差。
解决方法:采用广播方式,将单台Tomcat收到的注销请求广播给集群环境下的所有节点,达到所有服务器都注销的效果。核心代码:DMGeoSSOClient中的CasSingleLogoutClusterFilter.java。
配置方式,将DMGeoSSOClient工程下的lib目录下的jar包(servlet-api-2.3.jar除外)以及dist下的cas-client-core-3.1.3.jar包复制到集群环境所有Tomcat的lib目录,并修改所有tomcat的web.xml,增加过滤器的配置:
<filter>
<filter-name>CAS SLO Cluster Filter</filter-name>
<filter-class>org.esco.cas.client.CasSingleLogoutClusterFilter</filter-class>
<init-param>
<param-name>clientHostName</param-name>
<param-value>127.0.0.1:8080</param-value>
</init-param>
<init-param>
<param-name>peersUrls</param-name>
<param-value>http://127.0.0.1:8080,http://127.0.0.1:8081</param-value>
</init-param>
</filter>
clientHostName是本Tomcat的IP和端口,peersUrls是集群中所有节点的访问地址(格式为:协议://IP:端口,多个以","分隔),注意,这些IP地址和端口需要确保集群中所有的节点都能访问到。
另外,在集群中的所有需要做单点登录的应用中,web.xml中增加:
<filter-mapping>
<filter-name>CAS SLO Cluster Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:这个过滤器需要放在原单点注销的过滤器之前才有效。
Nginx+Tomcat+Memcached集群(简)
nginx配置:
nginx.conf:
upstream cluster {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
proxy.conf:
server {
listen 8888;
server_name 127.0.0.1;
#access_log logs/access.log main;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffer_size 1024k;
proxy_buffers 4 1024k;
proxy_busy_buffers_size 1024k;
proxy_temp_file_write_size 1024k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
proxy_max_temp_file_size 1024m;
location ~ ^/DMGeoPortal/ {
proxy_pass http://cluster;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/DMGeoSSO/ {
proxy_pass http://cluster;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Tomcat配置:
context.xml:
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.16.254.69:11211,n2:172.16.254.70:11211"
sticky="false"
sessionBackupAsync="false"
sessionBackupTimeout="18000"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
copyCollectionsForSerialization="false"
/>
server.xml:
<Engine name="Catalina" defaultHost="localhost">
注意:当sticky为false时,不需要配置jvmRoute属性,当sticky为true时,一定要配置jvmRoute属性,且集群中所有tomcat的jvmRoute属性均不一样。sticky的属性默认为true。在CAS服务器端集群和客户端集群环境下,需要将sticky配置为false,这样可以避免很多莫名其妙的session丢失问题。
Sticky 模式:tomcat session 为 主session, memcached 为备 session。Request请求到来时, 从memcached加载备 session 到 tomcat (仅当tomcat jvmroute发生变化时,否则直接取tomcat session);Request请求结束时,将tomcat session更新至memcached,以达到主备同步之目的。下面是sticky模式时响应的流程图(图片来源网络):
Non-Sticky模式:tomcat session 为 中转session, memcached1 为主 session,memcached 2 为备session。Request请求到来时,从memcached 2加载备 session 到 tomcat,(当 容器 中还是没有session 则从memcached1加载主 session 到 tomcat, 这种情况是只有一个memcached节点,或者有memcached1 出错时),Request请求结束时,将tomcat session更新至 主memcached1和备memcached2,并且清除tomcat session 。以达到主备同步之目的,如下是non-sticky模式的响应流程图:(图片来源网络)。

requestUriIgnorePattern属性不要设置。否则在CAS服务器端集群和客户端集群环境下有很多问题(包括影响注销功能,不能完全注销),因为我们的单点登录是对所有的资源进行拦截的,不需要设置requestUriIgnorePattern(URL忽略)属性。
集群中所有Tomcat的lib下新增的包:
javolution-5.4.3.1.jar
memcached-2.6.jar
memcached-session-manager-1.5.1.jar
memcached-session-manager-tc6-1.5.1.jar
msm-javolution-serializer-1.5.1.jar
msm-kryo-serializer-1.5.1.jar
msm-serializer-benchmark-1.5.1.jar
msm-xstream-serializer-1.5.1.jar
Nginx+IIS+Memcached集群(简)
nginx配置:
nginx.conf:
upstream dotnetcluster {
server 127.0.0.1:80;
server 127.0.0.1:81;
}
proxy.conf:
server {
listen 8888;
server_name 127.0.0.1;
#access_log logs/access.log main;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffer_size 1024k;
proxy_buffers 4 1024k;
proxy_busy_buffers_size 1024k;
proxy_temp_file_write_size 1024k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
proxy_max_temp_file_size 1024m;
location ~ ^/DMGeoGlobeWeb/ {
proxy_pass http://dotnetcluster;
proxy_set_header Host $host:8888;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/DMGeoMIS/ {
proxy_pass http://dotnetcluster;
proxy_set_header Host $host:8888;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
这里与Java应用稍有不同,注意上述红色加粗部分端口号的配置,该端口号是你最终访问集群服务器的端口号。
IIS配置:
将下列dll文件放在Web应用程序的bin目录:
Enyim.Caching.dll
MemcachedSessionProvider.dll
修改Web应用程序的Web.config配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="sessionManagement">
<section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
</sectionGroup>
</configSections>
<sessionManagement>
<memcached protocol="Binary">
<servers>
<!-- make sure you use the same ordering of nodes in every configuration you have -->
<add address="172.16.254.69" port="11211" />
<add address="172.16.254.70" port="11211" />
</servers>
<locator type="MemcachedSessionProvider.SessionNodeLocator, MemcachedSessionProvider" />
</memcached>
</sessionManagement>
<system.web>
<sessionState customProvider="Memcached" mode="Custom">
<providers>
<add name="Memcached" type="MemcachedSessionProvider.SessionProvider, MemcachedSessionProvider" />
</providers>
</sessionState>
<machineKey validationKey="3A2122BF7DA69398B43FF26BD658CE428EC417BA" decryptionKey="5C90C7D3BE69792117E02AE72DDDAFBA853F5FDB3E57BC5C" decryption="3DES" validation="SHA1"/>
</system.web>
</configuration>
上述红色加粗部分是新增的配置项。说明如下:
sessionManagement:用来配置Memcached连接地址。
sessionState:用将配置将Session存储在什么地方,这里配置的是自定义,即将Session存储在Memcached中。
machineKey:这是比较关键的配置。如果我们的Web应用程序是在同一个IIS服务器上,用不同的端口来区分不同的网站应用,那么不需要配置machineKey;如果我们的Web应用程序是在不同的IIS服务器上,那么切记一定要配置machineKey。machineKey是对密钥进行配置,以便将其用于对 Forms 身份验证 Cookie 数据和视图状态数据进行加密和解密,并将其用于对进程外会话状态标识进行验证。默认情况下,Asp.Net的配置是自己动态生成,如果单台服务器当然没问题,但是如果多台服务器负载均衡,machineKey还采用动态生成的方式,每台服务器上的machinekey值不一致,就导致加密出来的结果也不一致,不能共享验证和 ViewState,所以对于多台服务器负载均衡的情况,一定要在每个站点配置相同的machineKey。
machineKey的生成算法如下:
private static string CreateKey(int len)
{
byte[] bytes = new byte[len];
new RNGCryptoServiceProvider().GetBytes(bytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(string.Format("{0:X2}", bytes[i]));
}
return sb.ToString();
}
调用:
string validationKey = CreateKey(20);
string decryptionKey = CreateKey(24);
string machineKey = string.Format("<machineKey validationKey=\"{0}\" decryptionKey=\"{1}\" decryption=\"3DES\" validation=\"SHA1\"/>",validationKey, decryptionKey);
CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案的更多相关文章
- 单点登录(SSO)解决方案之 CAS客户端与Spring Security集成
接上篇:单点登录(SSO)解决方案之 CAS服务端数据源设置及页面改造 Spring Security Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制 ...
- 单点登录(SSO)解决方案之 CAS 入门案例
单点登录: 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. ...
- 单点登录(SSO)解决方案之 CAS服务端数据源设置及页面改造
接上篇 单点登录(SSO)解决方案之 CAS 入门案例 服务端数据源设置: 开发中,我们登录的user信息都是存在数据库中的,下面说一下如何让用户名密码从我们的数据库表中做验证. 案例中我最终把cas ...
- Object_C 集成环信时,中文环境下不显示中文
因为本app只有中文,没有做中英文判断,但是环信是默认英文环境的,所以,此时,需要在info.plist 文件中修改它的语言环境.如下
- 【Data Cluster】真机环境下MySQL数据库集群搭建
真机环境下MySQL-Cluster搭建文档 摘要:本年伊始阶段,由于实验室对不同数据库性能测试需求,才出现MySQL集群搭建.购置主机,交换机,双绞线等一系列准备工作就绪,也就开始集群搭建.起初笔 ...
- 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析
我的预想情况 一般情况下,当用户登录一个站点后,如果长时间没有发生任何动作,当用户再次点击时,会被强制登出并且跳转到登录页面, 提醒用户重新登录.现在我已经为站点整合了CAS,并且已经实现了单点登录以 ...
- Cas 服务器 Service(Cas客户端)注册信息维护
作为Cas服务器,允许哪些客户端接入与否是通过配置来定义的.对Cas服务器来说,每一个接入的客户端与一个Service配置对应:在Cas服务器启动时加载并注册上这些Service,与之对应的客户端才能 ...
- CAS5.3服务器搭建及SpringBoot整合CAS实现单点登录
1.1 什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的 ...
- cas单点登录系统:客户端(client)详细配置(包含统一单点注销配置)
最近一直在研究cas登录中心这一块的应用,分享一下记录的一些笔记和心得.后面会把cas-server端的配置和重构,另外还有这几天再搞nginx+cas的https反向代理配置,以及cas的证书相关的 ...
随机推荐
- UNIX基础概念
UNIX基本概念 进程 从用户观点来看:进程是程序的一个执行实例. 从UNIX系统内部来看,是为运行程序提供执行环境的实体,是系统进行资源分配和调度运行的一个单位. 进程有三个特点: 1)进程有一个控 ...
- Android屏幕尺寸单位转换
最近在看Android群英传这本书,书中有一节涉及到了,屏幕尺寸与单位.觉得以后可能会用到,做个笔记. PPI(pixels per inch) ,又称为DPI,它是由对角线的像素点数除以屏幕的大小得 ...
- eclipse左边的项目栏消失的处理方法
window —–> Show View —–> other —–> package Explorer
- MAVEN打zip包
https://blog.csdn.net/yulin_hu/article/details/81835945 https://www.cnblogs.com/f-zhao/p/6929814.htm ...
- [转] Akka 使用系列之二: 测试
[From] http://www.algorithmdog.com/akka-test 通过上一篇文章,我们已经大致了解怎么使用 Akka,期待细致用法.这篇文章将介绍如何用 Akka-testki ...
- Linux系统编程:文件I/O编程
文件I/O操作在Linux编程时是经常会使用到的一个内容,通常可以把比较大的数据写到一个文件中来进行存储或者与其他进程进行数据传输,这样比写到一个全局数组或指针参数来实现还要方便好多. 一.文件常用操 ...
- 【Eclipse】编译使用Makefile的C工程
创建MakeFile project新建src文件夹,将文件复制到里面.右击makefile,make targets->create->名称填上allmake targets->b ...
- 【Kafka源码】Kafka代码模块
Kafka源码依赖于Scala环境,首先需要安装scala,这块请自行百度进行安装. 传送门 当然,我们要分析源码,需要下载源码,请自行从github上面下载. 说明:本文使用的kafka版本为0.1 ...
- 深度学习(十六) ReLU为什么比Sigmoid效果好
sigmoid: Relu: 为什么通常Relu比sigmoid和tanh强,有什么不同?主要是因为它们gradient特性不同. 1.sigmoid和tanh的gradient在饱和区域非常平缓,接 ...
- spingAOP在springMVC中的使用(我用在拦截controller中的方法。主要用于登录控制)
首先截取了网上的一张配置execution的图片 我在项目中关于aop的配置:如果拦截controller的方法,需要在spring-mvc.xml文件中加入(如果在spring.xml中加入则无法拦 ...