CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况。在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户session所在的具体客户应用服务器,而不是转发到其他集群服务器上,二是解决CAS服务端集群环境下各种Ticket信息的共享。

  1. CAS集群部署

    由于CAS Server是一个Web应用,因此可部署在Tomcat等容器中。直接部署CAS集群并使用负载均衡配置后,由于每次访问的CAS Server不固定,会发生通行证丢失。

    解决方法:配置TOMCAT集群及Session复制,解决CAS Server Session复制。详细配置方法见"Nginx+Tomcat+Memcached集群"。

  2. 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的特性。

  3. 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>

    注意:这个过滤器需要放在原单点注销的过滤器之前才有效。

  4. 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

  5. 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服务器集群和客户端集群环境下的单点登录和单点注销解决方案的更多相关文章

  1. 单点登录(SSO)解决方案之 CAS客户端与Spring Security集成

    接上篇:单点登录(SSO)解决方案之 CAS服务端数据源设置及页面改造 Spring Security Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制 ...

  2. 单点登录(SSO)解决方案之 CAS 入门案例

    单点登录: 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. ...

  3. 单点登录(SSO)解决方案之 CAS服务端数据源设置及页面改造

    接上篇 单点登录(SSO)解决方案之 CAS 入门案例 服务端数据源设置: 开发中,我们登录的user信息都是存在数据库中的,下面说一下如何让用户名密码从我们的数据库表中做验证. 案例中我最终把cas ...

  4. Object_C 集成环信时,中文环境下不显示中文

    因为本app只有中文,没有做中英文判断,但是环信是默认英文环境的,所以,此时,需要在info.plist 文件中修改它的语言环境.如下

  5. 【Data Cluster】真机环境下MySQL数据库集群搭建

    真机环境下MySQL-Cluster搭建文档  摘要:本年伊始阶段,由于实验室对不同数据库性能测试需求,才出现MySQL集群搭建.购置主机,交换机,双绞线等一系列准备工作就绪,也就开始集群搭建.起初笔 ...

  6. 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析

    我的预想情况 一般情况下,当用户登录一个站点后,如果长时间没有发生任何动作,当用户再次点击时,会被强制登出并且跳转到登录页面, 提醒用户重新登录.现在我已经为站点整合了CAS,并且已经实现了单点登录以 ...

  7. Cas 服务器 Service(Cas客户端)注册信息维护

    作为Cas服务器,允许哪些客户端接入与否是通过配置来定义的.对Cas服务器来说,每一个接入的客户端与一个Service配置对应:在Cas服务器启动时加载并注册上这些Service,与之对应的客户端才能 ...

  8. CAS5.3服务器搭建及SpringBoot整合CAS实现单点登录

    1.1 什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的 ...

  9. cas单点登录系统:客户端(client)详细配置(包含统一单点注销配置)

    最近一直在研究cas登录中心这一块的应用,分享一下记录的一些笔记和心得.后面会把cas-server端的配置和重构,另外还有这几天再搞nginx+cas的https反向代理配置,以及cas的证书相关的 ...

随机推荐

  1. /proc/xxx/maps简要记录

    定位内存泄漏基本上是从宏观到微观,进而定位到代码位置. 从/proc/meminfo可以看到整个系统内存消耗情况,使用top可以看到每个进程的VIRT(虚拟内存)和RES(实际占用内存),基本上就可以 ...

  2. Hangfire JobStorage.Current property value has not been initialized

    app.UseHangfireServer() 放到 app.UseAbp() 前面 作者: zhaok 出处: http://dotnetmonkey.cnblogs.com/

  3. 我最近用Python写了一个算法,不需要写任何规则就能自动识别一个网页的内容

    我最近用Python写了一个算法,不需要写任何规则就能自动识别一个网页的内容,目前测试了300多个新闻网站的新闻页,都能准确识别

  4. 关于javascript的各种高宽

  5. 之前为dd写的一个小的demo(robotium)

    测试类的编写: package com.m1905.dd.mobile; import com.robotium.solo.By; import com.robotium.solo.Solo; imp ...

  6. Git fetch & pull 区别

    1 简单概括 2 git fetch 的用法 3 git pull的用法 文章来源:https://blog.csdn.net/qq_36113598/article/details/78906882

  7. mongo小记

    进mongo mongo 先添加admin表的账号密码 . use admin . db.createUser( { user: "admin", pwd: "admin ...

  8. Java测试各种数据库连接(用Connection类)

    源代码: package cn.finedo.fdcollect_service.util; import java.sql.Connection; import org.apache.logging ...

  9. JAVA标签

    java没有GOTO,可以通过标签实现跳转. 在 Java 里唯一需要用到标签的地方就是拥有嵌套循环,而且想中断或继续多个嵌套级别的时候. 使用位置:用在循环语句之前.----它实际需要紧靠在循环语句 ...

  10. 通过开机广播(broadcast)通知应用

    1. 概念 开机的时候,系统会发送一则广播,所有有标记的应用(通过广播接收者)都会获取得到,然后可以通过广播接收者去处理一些事情,比如启动该应用,或者处理数据: 代码:https://github.c ...