1. 360极速浏览器使用cas单点登录慢解决办法
360极速浏览器使用cas单点解决办法:
1、打开360极速浏览器,点击浏览器右上方“自定义和控制360极速浏览器”图标,在下方的菜单中点击打开“选项”页面。
2、进入选项页面后看向左侧的菜单栏中,点击“高级设置”这一项切换到对应的设置页面。
3、在右侧的高级设置内容中可以看到“隐私设置”这一项,点击右侧的“清除上网痕迹”按钮。
4、在弹出的“清除上网痕迹”窗口中将“清除这段时间的数据”修改为全部,然后勾选“清除缓存”这一项,其它的选项则可以选择性的勾选,然后点“清除”按钮就可以将缓存清除了。
2. 在tomcat中配置CAS
CAS原理和协议
从结构上看,CAS包含两个部分:CASServer和CASClient。CASServer需要独立部署,主要负责对用户的认证工作;CASClient负责处理对客户端受保护资源的访问请求,需要登录时,重定向到CASServer。图1是CAS最基本的协议过程:
图1.CAS基础协议
CASClient与受保护的客户端应用部署在一起,以Filter方式保护受保护的资源。对于访问受保护资源的每个Web请求,CASClient会分析该请求的Http请求中是否包含ServiceTicket,如果没有,则说明当前用户尚未登录,于是将请求重定向到指定好的CASServer登录地址,并传递Service(也就是要访问的目的资源地址),以便登录成功过后转回该地址。用户在第3步中输入认证信息,如果登录成功,CASServer随机产生一个相当长度、唯一、不可伪造的ServiceTicket,并缓存以待将来验证,之后系统自动重定向到Service所在地址,并为客户端浏览器设置一个TicketGrantedCookie(TGC),CASClient在拿到Service和新产生的Ticket过后,在第5,6步中与CASServer进行身份合适,以确保ServiceTicket的合法性。
在该协议中,所有与CAS的交互均采用SSL协议,确保,ST和TGC的安全性。协议工作过程中会有2次重定向的过程,但是CASClient与CASServer之间进行Ticket验证的过程对于用户是透明的。
另外,CAS协议中还提供了Proxy(代理)模式,以适应更加高级、复杂的应用场景,具体介绍可以参考CAS官方网站上的相关文档。
准备工作
本文中的例子以tomcat5.5为例进行讲解,下载地址:
http://tomcat.apache.org/download-55.cgi
到CAS官方网站下载CASServer和Client,地址分别为:
http://www.ja-sig.org/downloads/cas/cas-server-3.1.1-release.zip
http://www.ja-sig.org/downloads/cas-clients/cas-client-java-2.1.1.zip
部署CASServer
CASServer是一套基于Java实现的服务,该服务以一个JavaWebApplication单独部署在与servlet2.3兼容的Web服务器上,另外,由于Client与CASServer之间的交互采用Https协议,因此部署CASServer的服务器还需要支持SSL协议。当SSL配置成功过后,像普通Web应用一样将CASServer部署在服务器上就能正常运行了,不过,在真正使用之前,还需要扩展验证用户的接口。
在Tomcat上部署一个完整的CASServer主要按照以下几个步骤:
配置Tomcat使用Https协议
如果希望Tomcat支持Https,主要的工作是配置SSL协议,其配置过程和配置方法可以参考Tomcat的相关文档。不过在生成证书的过程中,会有需要用到主机名的地方,CAS建议不要使用IP地址,而要使用机器名或域名。
部署CASServer
CASServer是一个Web应用包,将前面下载的cas-server-3.1.1-release.zip解开,把其中的cas-server-webapp-3.1.1.war拷贝到tomcat的webapps目录,并更名为cas.war。由于前面已配置好tomcat的https协议,可以重新启动tomcat,然后访问:https://localhost:8443/cas,如果能出现正常的CAS登录页面,则说明CASServer已经部署成功。
虽然CASServer已经部署成功,但这只是一个缺省的实现,在实际使用的时候,还需要根据实际概况做扩展和定制,最主要的是扩展认证(Authentication)接口和CASServer的界面。
扩展认证接口
CASServer负责完成对用户的认证工作,它会处理登录时的用户凭证(Credentials)信息,用户名/密码对是最常见的凭证信息。CASServer可能需要到数据库检索一条用户帐号信息,也可能在XML文件中检索用户名/密码,还可能通过LDAPServer获取等,在这种情况下,CAS提供了一种灵活但统一的接口和实现分离的方式,实际使用中CAS采用哪种方式认证是与CAS的基本协议分离开的,用户可以根据认证的接口去定制和扩展。
扩展AuthenticationHandler
CAS提供扩展认证的核心是AuthenticationHandler接口,该接口定义如清单1下:
清单1.AuthenticationHandler定义
{
/**
*.
*@.
*@returntrueifvalid,returnfalseotherwise.
*@
*.
*/
booleanauthenticate(Credentialscredentials)throwsAuthenticationException;
/**
*
*provided.
*
*Credentialsobject.
*@.
*@,falseothewrise.
*/
booleansupports(Credentialscredentials);
}
该接口定义了2个需要实现的方法,supports()方法用于检查所给的包含认证信息的Credentials是否受当前AuthenticationHandler支持;而authenticate()方法则担当验证认证信息的任务,这也是需要扩展的主要方法,根据情况与存储合法认证信息的介质进行交互,返回boolean类型的值,true表示验证通过,false表示验证失败。
CAS3中还提供了对AuthenticationHandler接口的一些抽象实现,比如,可能需要在执行authenticate()方法前后执行某些其他操作,那么可以让自己的认证类扩展自清单2中的抽象类:
清单2.定义
publicabstractclass
implementsAuthenticateHandler{
protectedLoglog=LogFactory.getLog(this.getClass());
(finalCredentialscredentials){
returntrue;
}
(finalCredentialscredentials,
finalbooleanauthenticated){
returnauthenticated;
}
(finalCredentialscredentials)
throwsAuthenticationException{
if(!preAuthenticate(credentials)){
returnfalse;
}
finalbooleanauthenticated=doAuthentication(credentials);
returnpostAuthenticate(credentials,authenticated);
}
(finalCredentialscredentials)
throwsAuthenticationException;
}
类新定义了preAuthenticate()方法和postAuthenticate()方法,而实际的认证工作交由doAuthentication()方法来执行。因此,如果需要在认证前后执行一些额外的操作,可以分别扩展preAuthenticate()和ppstAuthenticate()方法,而doAuthentication()取代authenticate()成为了子类必须要实现的方法。
由于实际运用中,最常用的是用户名和密码方式的认证,CAS3提供了针对该方式的实现,如清单3所示:
清单3.定义
publicabstractclassextends
{
...
(finalCredentialscredentials)
throwsAuthenticationException{
((UsernamePasswordCredentials)credentials);
}
(
)throwsAuthenticationException;
(){
returnthis.passwordEncoder;
}
(){
this.passwordEncoder=passwordEncoder;
}
...
}
基于用户名密码的认证方式可直接扩展自,验证用户名密码的具体操作通过实现()方法达到,另外,通常情况下密码会是加密过的,setPasswordEncoder()方法就是用于指定适当的加密器。
从以上清单中可以看到,doAuthentication()方法的参数是Credentials类型,这是包含用户认证信息的一个接口,对于用户名密码类型的认证信息,可以直接使用UsernamePasswordCredentials,如果需要扩展其他类型的认证信息,需要实现Credentials接口,并且实现相应的接口,其具体方法可以借鉴UsernamePasswordCredentials和UsernamePassword。
JDBC认证方法
用户的认证信息通常保存在数据库中,因此本文就选用这种情况来介绍。将前面下载的cas-server-3.1.1-release.zip包解开后,在moles目录下可以找到包cas-server-support-jdbc-3.1.1.jar,其提供了通过JDBC连接数据库进行验证的缺省实现,基于该包的支持,我们只需要做一些配置工作即可实现JDBC认证。
JDBC认证方法支持多种数据库,DB2,Oracle,Mysql,MicrosoftSQLServer等均可,这里以DB2作为例子介绍。并且假设DB2数据库名:CASTest,数据库登录用户名:db2user,数据库登录密码:db2password,用户信息表为:userTable,该表包含用户名和密码的两个数据项分别为userName和password。
1.配置DataStore
打开文件%CATALINA_HOME%/webapps/cas/WEB-INF/deployerConfigContext.xml,添加一个新的bean标签,对于DB2,内容如清单4所示:
清单4.配置DataStore
<beanid="casDataSource"class="org.apache.commons.dbcp.BasicDataSource">
<propertyname="driverClassName">
<value>com.ibm.db2.jcc.DB2Driver</value>
</property>
<propertyname="url">
<value>jdbc:db2://9.125.65.134:50000/CASTest</value>
</property>
<propertyname="username">
<value>db2user</value>
</property>
<propertyname="password">
<value>db2password</value>
</property>
</bean>
其中id属性为该DataStore的标识,在后面配置AuthenticationHandler会被引用,另外,需要提供DataStore所必需的数据库驱动程序、连接地址、数据库登录用户名以及登录密码。
2.配置AuthenticationHandler
在cas-server-support-jdbc-3.1.1.jar包中,提供了3个基于JDBC的AuthenticationHandler,分别为,,。其中是用所给的用户名和密码去建立数据库连接,根据连接建立是否成功来判断验证成功与否;通过配置一个SQL语句查出密码,与所给密码匹配;通过配置存放用户验证信息的表、用户名字段和密码字段,构造查询语句来验证。
使用哪个AuthenticationHandler,需要在deployerConfigContext.xml中设置,默认情况下,CAS使用一个简单的username=password的AuthenticationHandler,在文件中可以找到如下一行:<beanclass="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePassword
AuthenticationHandler"/>,我们可以将其注释掉,换成我们希望的一个AuthenticationHandler,比如,使用或可以分别选取清单5或清单6的配置。
清单5.使用
<beanclass="org.jasig.cas.adaptors.jdbc.">
<propertyname="dataSource"ref="casDataSource"/>
<propertyname="sql"
value="(userName)=lower(?)"/>
</bean>
清单6.使用
<beanid=""
class="org.jasig.cas.adaptors.jdbc."
abstract="false"singleton="true"lazy-init="default"
autowire="default"dependency-check="default">
<propertyname="tableUsers">
<value>userTable</value>
</property>
<propertyname="fieldUser">
<value>userName</value>
</property>
<propertyname="fieldPassword">
<value>password</value>
</property>
<propertyname="dataSource"ref="casDataSource"/>
</bean>
另外,由于存放在数据库中的密码通常是加密过的,所以AuthenticationHandler在匹配时需要知道使用的加密方法,在deployerConfigContext.xml文件中我们可以为具体的AuthenticationHandler类配置一个property,指定加密器类,比如对于,可以修改如清单7所示:
清单7.添加passwordEncoder
<beanclass="org.jasig.cas.adaptors.jdbc.">
<propertyname="dataSource"ref="casDataSource"/>
<propertyname="sql"
value="(userName)=lower(?)"/>
<propertyname="passwordEncoder"ref="myPasswordEncoder"/>
</bean>
其中myPasswordEncoder是对清单8中设置的实际加密器类的引用:
清单8.指定具体加密器类
<beanid="passwordEncoder"
class="org.jasig.cas.authentication.handler.MyPasswordEncoder"/>
这里MyPasswordEncoder是根据实际情况自己定义的加密器,实现PasswordEncoder接口及其encode()方法。
3.部署依赖包
在以上配置完成以后,需要拷贝几个依赖的包到cas应用下,包括:
将cas-server-support-jdbc-3.1.1.jar拷贝到%CATALINA_HOME%/webapps/cas/WEB-INF/lib目录。
数据库驱动,由于这里使用DB2,将%DB2_HOME%/java目录下的db2java.zip(更名为db2java.jar),db2jcc.jar,db2jcc_license_cu.jar拷贝到%CATALINA_HOME%/webapps/cas/WEB-INF/lib目录。对于其他数据库,同样将相应数据库驱动程序拷贝到该目录。
DataStore依赖于commons-collections-3.2.jar,commons-dbcp-1.2.1.jar,commons-pool-1.3.jar,需要到apache网站的Commons项目下载以上3个包放进%CATALINA_HOME%/webapps/cas/WEB-INF/lib目录。
扩展CASServer界面
CAS提供了2套默认的页面,分别为“default”和“simple”,分别在目录“cas/WEB-INF/view/jsp/default”和“cas/WEB-INF/view/jsp/simple”下。其中default是一个稍微复杂一些的页面,使用CSS,而simple则是能让CAS正常工作的最简化的页面。
在部署CAS之前,我们可能需要定制一套新的CASServer页面,添加一些个性化的内容。最简单的方法就是拷贝一份default或simple文件到“cas/WEB-INF/view/jsp”目录下,比如命名为newUI,接下来是实现和修改必要的页面,有4个页面是必须的:
casConfirmView.jsp:当用户选择了“warn”时会看到的确认界面
casGenericSuccess.jsp:在用户成功通过认证而没有目的Service时会看到的界面
casLoginView.jsp:当需要用户提供认证信息时会出现的界面
casLogoutView.jsp:当用户结束CAS单点登录系统会话时出现的界面
CAS的页面采用Spring框架编写,对于不熟悉Spring的使用者,在修改之前需要熟悉该框架。
页面定制完过后,还需要做一些配置从而让CAS找到新的页面,拷贝“cas/WEB-INF/classes/default_views.properties”,重命名为“cas/WEB-INF/classes/newUI_views.properties”,并修改其中所有的值到相应新页面。最后是更新“cas/WEB-INF/cas-servlet.xml”文件中的viewResolver,将其修改为如清单9中的内容。
清单9.指定CAS页面
<beanid="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver"p:order="0">
<propertyname="basenames">
<list>
<value>${cas.viewResolver.basename}</value>
<value>newUI_views</value>
</list>
</property>
</bean>
部署客户端应用
单点登录的目的是为了让多个相关联的应用使用相同的登录过程,本文在讲解过程中构造2个简单的应用,分别以casTest1和casTest2来作为示例,它们均只有一个页面,显示欢迎信息和当前登录用户名。这2个应用使用同一套登录信息,并且只有登录过的用户才能访问,通过本文的配置,实现单点登录,即只需登录一次就可以访问这两个应用。
与CASServer建立信任关系
假设CASServer单独部署在一台机器A,而客户端应用部署在机器B上,由于客户端应用与CASServer的通信采用SSL,因此,需要在A与B的JRE之间建立信任关系。
首先与A机器一样,要生成B机器上的证书,配置Tomcat的SSL协议。其次,下载http://blogs.sun.com/andreas/entry/no_more_unable_to_find的InstallCert.java,运行“javaInstallCertcompA:8443”命令,并且在接下来出现的询问中输入1。这样,就将A添加到了B的truststore中。如果多个客户端应用分别部署在不同机器上,那么每个机器都需要与CASServer所在机器建立信任关系。
配置CASFilter
准备好应用casTest1和casTest2过后,分别部署在B和C机器上,由于casTest1和casTest2,B和C完全等同,我们以casTest1在B机器上的配置做介绍,假设A和B的域名分别为domainA和domainB。
将cas-client-java-2.1.1.zip改名为cas-client-java-2.1.1.jar并拷贝到casTest1/WEB-INF/lib目录下,修改web.xml文件,添加CASFilter,如清单10所示:
清单10.添加CASFilter
<web-app>
...
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>e.yale.its.tp.cas.client.filter.CASFilter</filter-class>
<init-param>
<param-name>e.yale.its.tp.cas.client.filter.loginUrl</param-name>
<param-value>https://domainA:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>e.yale.its.tp.cas.client.filter.validateUrl</param-name>
<param-value>https://domainA:8443/cas/serviceValidate</param-value>
</init-param>
<init-param>
<param-name>e.yale.its.tp.cas.client.filter.serverName</param-name>
<param-value>domainB:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/protected-pattern/*</url-pattern>
</filter-mapping>
...
</web-app>
对于所有访问满足casTest1/protected-pattern/路径的资源时,都要求到CASServer登录,如果需要整个casTest1均受保护,可以将url-pattern指定为“/*”。
从清单10可以看到,我们可以为CASFilter指定一些参数,并且有些是必须的,表格1和表格2中分别是必需和可选的参数:
表格1.CASFilter必需的参数
参数名作用
e.yale.its.tp.cas.client.filter.loginUrl指定CAS提供登录页面的URL
e.yale.its.tp.cas.client.filter.validateUrl指定CAS提供serviceticket或proxyticket验证服务的URL
e.yale.its.tp.cas.client.filter.serverName指定客户端的域名和端口,是指客户端应用所在机器而不是CASServer所在机器,该参数或serviceUrl至少有一个必须指定
e.yale.its.tp.cas.client.filter.serviceUrl该参数指定过后将覆盖serverName参数,成为登录成功过后重定向的目的地址
表格2.CASFilter可选参数
参数名作用
e.yale.its.tp.cas.client.filter.proxyCallbackUrl用于当前应用需要作为其他服务的代理(proxy)时获取ProxyGrantingTicket的地址
e.yale.its.tp.cas.client.filter.authorizedProxy用于允许当前应用从代理处获取proxytickets,该参数接受以空格分隔开的多个proxyURLs,但实际使用只需要一个成功即可。当指定该参数过后,需要修改validateUrl到proxyValidate,而不再是serviceValidate
e.yale.its.tp.cas.client.filter.renew如果指定为true,那么受保护的资源每次被访问时均要求用户重新进行验证,而不管之前是否已经通过
e.yale.its.tp.cas.client.filter.wrapRequest如果指定为true,那么CASFilter将重新包装HttpRequest,并且使getRemoteUser()方法返回当前登录用户的用户名
e.yale.its.tp.cas.client.filter.gateway指定gateway属性
传递登录用户名
CAS在登录成功过后,会给浏览器回传Cookie,设置新的到的ServiceTicket。但客户端应用拥有各自的Session,我们要怎么在各个应用中获取当前登录用户的用户名呢?CASClient的Filter已经做好了处理,在登录成功后,就可以直接从Session的属性中获取,如清单11所示:
清单11.在Java中通过Session获取登录用户名
//以下两者都可以
session.getAttribute(CASFilter.CAS_FILTER_USER);
session.getAttribute("e.yale.its.tp.cas.client.filter.user");
在JSTL中获取用户名的方法如清单12所示:
清单12.通过JSTL获取登录用户名
<c:outvalue="${sessionScope[CAS:'e.yale.its.tp.cas.client.filter.user']}"/>
另外,CAS提供了一个CASFilterRequestWrapper类,该类继承自HttpServletRequestWrapper,主要是重写了getRemoteUser()方法,只要在前面配置CASFilter的时候为其设置“e.yale.its.tp.cas.client.filter.wrapRequest”参数为true,就可以通过getRemoteUser()方法来获取登录用户名,具体方法如清单13所示:
清单13.通过CASFilterRequestWrapper获取登录用户名
=newCASFilterRequestWrapper(request);
out.println("Thelogonuser:"+reqWrapper.getRemoteUser());
3. CAS架构与原理简介
HTTP是无状态协议,客户端与服务端之间的每次通信都是独立的,而会话机制可以让服务端鉴别每次通讯过程中的客户端是否是同一个,从而保证业务的关联性。 Session是服务器使用一种类似于散列表的结构,用来保存用户会话所需要的信息.Cookie作为浏览器缓存,存储Session ID以达到会话跟踪的目的。
SSO 单点登录,是企业为了解决在相互信任的系统上实现一次登录的解决方案。SSO将一个企业内部所有域中的用户登录和用户帐号管理集中到一起,SSO的好处显而易见:
CAS是SSO解决方案里面比较成熟的架构,是耶鲁大学发起的一个开源架构,其旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点:
下图是 CAS 最基本的协议过程:
CAS架构包括两部分:CAS Server和CAS Client。
以下是CAS应用之间交互过程的详细时序图与说明。
4. VS2010 此方法显式使用的 CAS 策略已被 .NET Framework 弃用。NetFx40_LegacySecurityPolicy 配置开关
将
<NetFx40_LegacySecurityPolicy enabled="true"/>
作为第一项添加到C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe.config文件中的<runtime>标签下,保存文件
5. 登录那点事
client:提供用户名和密码或者是其他的认证凭证
server:验证client提供的认证凭证,记录登录状态
过程:访问系统时,client必须输入用户名和密码,server进行验证,验证通过后server建立一个叫做session的东西,然后把sessionId通过cookie发送给浏览器,下次登录的时候会带着cookie一起发过来,server从cookie中拿到sessionId就知道已经登录啦。
cookie和session的作用就是保持client和server的交互状态,这样一来可以将无状态的通信转化成有状态的交互,也就是让server有了“记忆”能力。
现在有三个服务,需要输入三次用户信息,但是如果有成百上千的服务呢?HOW???
参考上面简单登录的原理:服务端如何有了“记忆”能力呢:在client和server之间引入了一个中间层(cookie或者是session)。(题外话:计算机世界的99%的问题都可以通过一个引入一个中间层来解决)
所有我们可以想到一个可行的解决方案:对这个“中间层”做共享。
比如说先登录了A,就有了一个cookie,然后在用cookie去登录其他的系统。但是这样明显是有问题的:
1,cookie不能跨域,比如说a.com产生的cookie是不能传递给b.com的
2,就算cookie可以传递,但是其他系统并没有session来校验这个cookie。
解决方案:
1.cookie做共享可以挂到同一个一级域名下,比如A叫a.corp.com,B叫b.corp.com,C叫c.corp.com,这样cookie不就能共享了嘛
2,将session也做共享,从内存里面拿出来,放入一个大家都能访问的中间层里面,比如说redis。(题外话:又是中间层)
像下面这样:
可以解决多系统登录的问题么?可以解决!!! 但是
1,要共享cookie就必须让所有的系统都在同一个域名下
2,多用户账号的存在。比如张三登录了A,然后去登录B,通过这种方式的话B需要去校验张三这个用户的合法性,此张三可能未必是彼张三!各个业务系统必须自己去维护自己系统的用户,而且用户信息还不止一个。
HOW????
Single Sign One :单点登录
消除多用户信息的问题,不用各个业务系统自己去维护用户信息,建立一个统一的用户认证中心(中间层:又是我哈哈哈),所有用户的认证工作都交给这个认证中心来完成。各个子业务只需要负责实现自己的业务即可,不在需要关心用户、认证等细节。
大致流程如下:
用户第一次访问A系统:www.a.corp.com,这个时候如果A发现用户没有登录的话,那他需要做的一项操作就是重定向认证中心:www.sso.com/login?redirect=www.a.corp.com。
其中www.sso.com/login就是认证中心的登录地址,redirect=www.a.corp.com就是登录完成后需要跳转到的地址。在认证中心登录之后认证中心会做以下几件事情:
1,建立一个session
2,发放ticket
3,重定向到你的地址,并在浏览器种下cookie信息。注意这个cookie是认证中心服务器的cookie哦。如:ssoid=1,domain=sso.com
需要注意的有两点:
1,进行了两次重定向。第一次是重定向到SSO的服务器,第二次是重定向我们的后端服务器。
2,流程完成后再浏览器种了两个cookie,一个是sso服务器的cookie,一个是子系统A的cookie。
接下来我们访问B系统:
这个时候会有三个cookie:
1,认证中心的cookie domain: sso.com
2,A系统的cookie domain: a.corp.com
3, B系统的cookie domain: b.corp.com
本质上就是保存了一个认证中心的cookie和多个子系统的cookie。一般我们称SSO的cookie的对应的会话成为全局会话,各自子系统cookie对应的会话称为局部会话。
概述
CAS(Central Authentication Service) 是 Yale 大学发起的一个企业级的、开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO)。
CAS 开始于 2001 年, 并在 2004 年 12 月正式成为 JA-SIG 的一个项目。
特性
1、 开源的、多协议的 SSO 解决方案;Protocols:Custom Protocol、CAS、OAuth、OpenID、RESTful API、SAML1.1、SAML2.0 等。
2、 支持多种认证机制:Active Directory、JAAS、JDBC、LDAP、X.509 Certificates 等;
3、 安全策略:使用票据(Ticket)来实现支持的认证协议;
4、 支持授权:可以决定哪些服务可以请求和验证服务票据(Service Ticket);
5、 提供高可用性:通过把认证过的状态数据存储在 TicketRegistry 组件中,这些组件有很多支持分布式环境的实现,如:BerkleyDB、Default 、EhcacheTicketRegistry、JDBCTicketRegistry、JBOSS TreeCache、JpaTicketRegistry、MemcacheTicketRegistry 等;
6、 支持多种客户端: Java、 .Net、 PHP、 Perl、 Apache, uPortal 等。
体系结构
从结构上看,CAS 包含两个部分:CAS Server 和 CAS Client,CAS 需要独立部署,主要负责对用户的认证工作,CAS Server 会处理用户名 / 密码等凭证 (Credentials)。
负责处理对客户端受保护资源的访问请求,需要对请求方进行身份认证时,重定向到 CAS Server 进行认证。CAS Client一般与 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源。过滤从客户端过来的每一个 Web 请求,同时, CAS Client 会分析 HTTP 请求中是否包请求 Service Ticket
术语
Ticket Granting ticket (TGT) :可以认为是CAS Server根据用户名密码生成的一张票,存在server端
Ticket-granting cookie (TGC) :其实就是一个cookie,存放用户身份信息,由server发给client端
Service ticket (ST) :由TGT生成的一次性票据,用于验证,只能用一次。相当于server发给client一张票,然后client拿着这是个票再来找server验证,看看是不是server签发的。就像是我给了你一张我的照片,然后你拿照片再来问我,这个照片是不是你。。。没错,就是这么无聊。
安全性
TGC安全性:
对于一个 CAS 用户来说,最重要是要保护它的 TGC,如果 TGC 不慎被 CAS Server 以外的实体获得,Hacker 能够找到该 TGC,然后冒充 CAS 用户访问所有授权资源。从基础模式可以看出, TGC 是 CAS Server 通过 SSL 方式发送给终端用户,因此,要截取 TGC 难度非常大,从而确保 CAS 的安全性。TGT 的存活周期默认为 120 分钟。
ST安全性:
ST(Service Ticket)是通过 Http 传送的,因此网络中的其他人可以 Sniffer 到其他人的 Ticket。CAS 通过以下几方面来使 ST 变得更加安全:
1、 ST 只能使用一次
CAS 协议规定,无论 Service Ticket 验证是否成功, CAS Server 都会清除服务端缓存中的该 Ticket,从而可以确保一个 Service Ticket 不被使用两次。
2、 ST 在一段时间内失效
CAS 规定 ST 只能存活一定的时间,然后 CAS Server 会让它失效。默认有效时间为 5 分钟。
3、 ST 是基于随机数生成的
ST 必须足够随机,如果 ST 生成规则被猜出,Hacker 就等于绕过 CAS 认证,直接访问对应的服务。
流程
上图是3个登录场景,分别为:第一次访问www.qian.com、第二次访问、以及登录状态下第一次访问mail.qian.com。
第一次访问www.qian.com
标号1: 用户访问http://www.qian.com,经过他的第一个过滤器:org.jasig.cas.client.authentication.AuthenticationFilter(cas提供,在web.xml中配置)。主要作用:判断是否登录,如果没有登录则重定向到认证中心
标号2: www.qian.com发现用户没有登录,则返回浏览器重定向地址。
首先可以看到我们请求www.qian.com,之后浏览器返回状态码302,然后让浏览器重定向到cas.qian.com并且通过get的方式添加参数service,该参数目的是登录成功之后会要重定向回来,因此需要该参数。并且你会发现,其实server的值就是编码之后的我们请求www.qian.com的地址。
标号3: 浏览器接收到重定向之后发起重定向,请求cas.qian.com。
标号4: 认证中心cas.qian.com接收到登录请求,返回登陆页面。
上图就是标号3的请求,以及标号4的响应。请求的URL是标号2返回的URL。之后认证中心就展示登录的页面,等待用户输入用户名密码。
标号5: 用户在cas.qian.com的login页面输入用户名密码,提交。
标号6 :服务器接收到用户名密码,则验证是否有效,验证逻辑可以使用cas-server提供现成的,也可以自己实现。
上图就是标号5的请求,以及标号6的响应了。当cas.qian.com即csa-server认证通过之后,会返回给浏览器302,重定向的地址就是Referer中的service参数对应的值。后边并通过get的方式挟带了一个ticket令牌,这个ticket就是ST(数字3处)。同时会在Cookie中设置一个CASTGC,该cookie是网站cas.qian.com的cookie,只有访问这个网站才会携带这个cookie过去。
Cookie中的CASTGC:向cookie中添加该值的目的是当下次访问cas.qian.com时,浏览器将Cookie中的TGC携带到服务器,服务器根据这个TGC,查找与之对应的TGT。从而判断用户是否登录过了,是否需要展示登录页面。TGT与TGC的关系就像SESSION与Cookie中SESSIONID的关系。点击这里了解Java如何操作Cookie。
TGT:Ticket Granted Ticket(俗称大令牌,或者说票根,他可以签发ST)
TGC:Ticket Granted Cookie(cookie中的value),存在Cookie中,根据他可以找到TGT。
ST:Service Ticket (小令牌),是TGT生成的,默认是用一次就生效了。也就是上面数字3处的ticket值。
标号7 :浏览器从cas.qian.com哪里拿到ticket之后,就根据指示重定向到www.qian.com,请求的url就是上面返回的url。
标号8 :www.qian.com在过滤器中会取到ticket的值,然后通过http方式调用cas.qian.com验证该ticket是否是有效的。
标号9 :cas.qian.com接收到ticket之后,验证,验证通过返回结果告诉www.qian.com该ticket有效。
标号10 :www.qian.com接收到cas-server的返回,知道了用户合法,展示相关资源到用户浏览器上。
第二次访问www.qian.com
标号11 :用户发起请求,访问www.qian.com。会经过cas-client,也就是过滤器,因为第一次访问成功之后www.qian.com中会在session中记录用户信息,因此这里直接就通过了,不用验证了。
标号12 :用户通过权限验证,浏览器返回正常资源。
访问mail.qian.com
标号13 :用户在www.qian.com正常上网,突然想访问mail.qian.com,于是发起访问mail.qian.com的请求。
标号14 :mail.qian.com接收到请求,发现第一次访问,于是给他一个重定向的地址,让他去找认证中心登录。
上图可以看到,用户请求mail.qian.com,然后返回给他一个网址,状态302重定向,service参数就是回来的地址。
标号15 :浏览器根据14返回的地址,发起重定向,因为之前访问过一次了,因此这次会携带上次返回的Cookie:TGC到认证中心。
标号16 :认证中心收到请求,发现TGC对应了一个TGT,于是用TGT签发一个ST,并且返回给浏览器,让他重定向到mail.qian.com
可以发现请求的时候是携带Cookie:CASTGC的,响应的就是一个地址加上TGT签发的ST也就是ticket。
标号17 :浏览器根据16返回的网址发起重定向。
标号18 :mail.qian.com获取ticket去认证中心验证是否有效。
标号19 :认证成功,返回在mail.qian.com的session中设置登录状态,下次就直接登录。
标号20 :认证成功之后就反正用想要访问的资源了。
配置filter
我们需要在应用的web.xml文件中配置四个Filter,这四个Filter必须按照固定的顺序来进行配置,而且它们必须配置在应用的其它Filter之前。它们的先后顺序要求如下:
1、AuthenticationFilter
casServerLoginUrl用来指定Cas Server登录地址,serverName或service用来指定认证成功后需要跳转地址。
2、TicketValidationFilter
请求通过AuthenticationFilter的认证之后,如果请求中携带了参数ticket则将会由TicketValidationFilter来对携带的ticket进行校验。 TicketValidationFilter只是对验证ticket的这一类Filter的统称,其并不对应Cas Client中的一个具体类型。Cas Client中有多种验证ticket的Filter,
都继承自,它们的验证逻辑都是一致的,都有实现,不同的是使用的TicketValidator不一样。这里我们使用Cas10TicketValidationFilter,也可以使用或Saml11TicketValidationFilter。
3、
用于将每一个请求对应的HttpServletRequest封装为其内部定义的CasHttpServletRequestWrapper,该封装类将利用之前保存在Session或request中的Assertion对象重写HttpServletRequest的getUserPrincipal()、getRemoteUser()和isUserInRole()方法。
这样在我们的应用中就可以非常方便的从HttpServletRequest中获取到用户的相关信息
4、AssertionThreadLocalFilter
AssertionThreadLocalFilter可以在应用的其它地方获取Assertion对象,找个过滤器会把Assertion对象存放到当前的线程变量中,我们在程序的任何地方都可以从线程变量中获取当前Assertion,就不需要再从Session或request中进行解析了。这个线程变量是由AssertionHolder持有的,我们在获取当前的 Assertion时也只需要通过AssertionHolder的getAssertion()方法获取即可
6. 什么是CAS
CAS意为列地址选通脉冲(Column Address Strobe 或者Column Address Select),CAS控制着从收到命令到执行命令的间隔时间,通常为2,2.5,3这个几个时钟周期。在整个内存矩阵中,因为CAS按列地址管理物理地址,因此在稳定的基础上,这个非常重要的参数值越低越好。过程是这样的,在内存阵列中分为行和列,当命令请求到达内存后,首先被触发的是tRAS (Active to Precharge Delay),数据被请求后需预先充电,一旦tRAS被激活后,RAS才开始在一半的物理地址中寻址,行被选定后,tRCD初始化,最后才通过CAS找到精确的地址。整个过程也就是先行寻址再列寻址。从CAS开始到CAS结束就是现在讲解的CAS延迟了。因为CAS是寻址的最后一个步骤,所以在内存参数中它是最重要的。
7. cas是什么
CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议。CAS 是耶鲁大学(Yale University)发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。
从结构上看,CAS 包含两个部分: CAS Server 和 CAS Client。CAS Server 需要独立部署,主要负责对用户的认证工作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。
相关信息:
CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源。对于访问受保护资源的每个 Web 请求,CAS Client 会分析该请求的 Http 请求中是否包含 Service Ticket,如果没有,则说明当前用户尚未登录。
于是将请求重定向到指定好的 CAS Server 登录地址,并传递 Service (也就是要访问的目的资源地址),以便登录成功过后转回该地址。用户在第 3 步中输入认证信息,如果登录成功,CAS Server 随机产生一个相当长度、唯一、不可伪造的 Service Ticket,并缓存以待将来验证,之后系统自动重定向到 Service 所在地址。
并为客户端浏览器设置一个 Ticket Granted Cookie(TGC),CAS Client 在拿到 Service 和新产生的 Ticket 过后,在第 5,6 步中与 CAS Server 进行身份核实,以确保 Service Ticket 的合法性。